summaryrefslogtreecommitdiff
path: root/sound/soc/codecs
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs')
-rw-r--r--sound/soc/codecs/ab8500-codec.c1
-rw-r--r--sound/soc/codecs/adau1761-i2c.c14
-rw-r--r--sound/soc/codecs/adau1761-spi.c14
-rw-r--r--sound/soc/codecs/adau1761.c10
-rw-r--r--sound/soc/codecs/adau1781-i2c.c10
-rw-r--r--sound/soc/codecs/adau1781-spi.c10
-rw-r--r--sound/soc/codecs/adau1781.c2
-rw-r--r--sound/soc/codecs/ads117x.c12
-rw-r--r--sound/soc/codecs/arizona.c71
-rw-r--r--sound/soc/codecs/arizona.h4
-rw-r--r--sound/soc/codecs/cs47l24.c123
-rw-r--r--sound/soc/codecs/wm5102.c93
-rw-r--r--sound/soc/codecs/wm5110.c75
-rw-r--r--sound/soc/codecs/wm8997.c2
-rw-r--r--sound/soc/codecs/wm8998.c2
-rw-r--r--sound/soc/codecs/wm_adsp.c131
-rw-r--r--sound/soc/codecs/wm_adsp.h8
17 files changed, 438 insertions, 144 deletions
diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c
index faae693..8b1d0c1 100644
--- a/sound/soc/codecs/ab8500-codec.c
+++ b/sound/soc/codecs/ab8500-codec.c
@@ -2134,7 +2134,6 @@ static int ab8500_codec_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
"%s: ERROR: Unsupporter master mask 0x%x\n",
__func__, fmt & SND_SOC_DAIFMT_MASTER_MASK);
return -EINVAL;
- break;
}
snd_soc_update_bits(codec, AB8500_DIGIFCONF3, mask, val);
diff --git a/sound/soc/codecs/adau1761-i2c.c b/sound/soc/codecs/adau1761-i2c.c
index 348ccb1..8de010f 100644
--- a/sound/soc/codecs/adau1761-i2c.c
+++ b/sound/soc/codecs/adau1761-i2c.c
@@ -1,5 +1,5 @@
/*
- * Driver for ADAU1761/ADAU1461/ADAU1761/ADAU1961 codec
+ * Driver for ADAU1361/ADAU1461/ADAU1761/ADAU1961 codec
*
* Copyright 2014 Analog Devices Inc.
* Author: Lars-Peter Clausen <lars@metafoo.de>
@@ -44,9 +44,21 @@ static const struct i2c_device_id adau1761_i2c_ids[] = {
};
MODULE_DEVICE_TABLE(i2c, adau1761_i2c_ids);
+#if defined(CONFIG_OF)
+static const struct of_device_id adau1761_i2c_dt_ids[] = {
+ { .compatible = "adi,adau1361", },
+ { .compatible = "adi,adau1461", },
+ { .compatible = "adi,adau1761", },
+ { .compatible = "adi,adau1961", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, adau1761_i2c_dt_ids);
+#endif
+
static struct i2c_driver adau1761_i2c_driver = {
.driver = {
.name = "adau1761",
+ .of_match_table = of_match_ptr(adau1761_i2c_dt_ids),
},
.probe = adau1761_i2c_probe,
.remove = adau1761_i2c_remove,
diff --git a/sound/soc/codecs/adau1761-spi.c b/sound/soc/codecs/adau1761-spi.c
index 8bc1fbd..d917124 100644
--- a/sound/soc/codecs/adau1761-spi.c
+++ b/sound/soc/codecs/adau1761-spi.c
@@ -1,5 +1,5 @@
/*
- * Driver for ADAU1761/ADAU1461/ADAU1761/ADAU1961 codec
+ * Driver for ADAU1361/ADAU1461/ADAU1761/ADAU1961 codec
*
* Copyright 2014 Analog Devices Inc.
* Author: Lars-Peter Clausen <lars@metafoo.de>
@@ -61,9 +61,21 @@ static const struct spi_device_id adau1761_spi_id[] = {
};
MODULE_DEVICE_TABLE(spi, adau1761_spi_id);
+#if defined(CONFIG_OF)
+static const struct of_device_id adau1761_spi_dt_ids[] = {
+ { .compatible = "adi,adau1361", },
+ { .compatible = "adi,adau1461", },
+ { .compatible = "adi,adau1761", },
+ { .compatible = "adi,adau1961", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, adau1761_spi_dt_ids);
+#endif
+
static struct spi_driver adau1761_spi_driver = {
.driver = {
.name = "adau1761",
+ .of_match_table = of_match_ptr(adau1761_spi_dt_ids),
},
.probe = adau1761_spi_probe,
.remove = adau1761_spi_remove,
diff --git a/sound/soc/codecs/adau1761.c b/sound/soc/codecs/adau1761.c
index 2f12477..b95d29d 100644
--- a/sound/soc/codecs/adau1761.c
+++ b/sound/soc/codecs/adau1761.c
@@ -1,5 +1,5 @@
/*
- * Driver for ADAU1761/ADAU1461/ADAU1761/ADAU1961 codec
+ * Driver for ADAU1361/ADAU1461/ADAU1761/ADAU1961 codec
*
* Copyright 2011-2013 Analog Devices Inc.
* Author: Lars-Peter Clausen <lars@metafoo.de>
@@ -456,13 +456,17 @@ static int adau1761_set_bias_level(struct snd_soc_codec *codec,
case SND_SOC_BIAS_PREPARE:
break;
case SND_SOC_BIAS_STANDBY:
+ regcache_cache_only(adau->regmap, false);
regmap_update_bits(adau->regmap, ADAU17X1_CLOCK_CONTROL,
ADAU17X1_CLOCK_CONTROL_SYSCLK_EN,
ADAU17X1_CLOCK_CONTROL_SYSCLK_EN);
+ if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF)
+ regcache_sync(adau->regmap);
break;
case SND_SOC_BIAS_OFF:
regmap_update_bits(adau->regmap, ADAU17X1_CLOCK_CONTROL,
ADAU17X1_CLOCK_CONTROL_SYSCLK_EN, 0);
+ regcache_cache_only(adau->regmap, true);
break;
}
@@ -783,6 +787,10 @@ int adau1761_probe(struct device *dev, struct regmap *regmap,
if (ret)
return ret;
+ /* Enable cache only mode as we could miss writes before bias level
+ * reaches standby and the core clock is enabled */
+ regcache_cache_only(regmap, true);
+
return snd_soc_register_codec(dev, &adau1761_codec_driver, dai_drv, 1);
}
EXPORT_SYMBOL_GPL(adau1761_probe);
diff --git a/sound/soc/codecs/adau1781-i2c.c b/sound/soc/codecs/adau1781-i2c.c
index 0e32bba..06cbca8 100644
--- a/sound/soc/codecs/adau1781-i2c.c
+++ b/sound/soc/codecs/adau1781-i2c.c
@@ -42,9 +42,19 @@ static const struct i2c_device_id adau1781_i2c_ids[] = {
};
MODULE_DEVICE_TABLE(i2c, adau1781_i2c_ids);
+#if defined(CONFIG_OF)
+static const struct of_device_id adau1781_i2c_dt_ids[] = {
+ { .compatible = "adi,adau1381", },
+ { .compatible = "adi,adau1781", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, adau1781_i2c_dt_ids);
+#endif
+
static struct i2c_driver adau1781_i2c_driver = {
.driver = {
.name = "adau1781",
+ .of_match_table = of_match_ptr(adau1781_i2c_dt_ids),
},
.probe = adau1781_i2c_probe,
.remove = adau1781_i2c_remove,
diff --git a/sound/soc/codecs/adau1781-spi.c b/sound/soc/codecs/adau1781-spi.c
index 33a73ff..3d965a0 100644
--- a/sound/soc/codecs/adau1781-spi.c
+++ b/sound/soc/codecs/adau1781-spi.c
@@ -59,9 +59,19 @@ static const struct spi_device_id adau1781_spi_id[] = {
};
MODULE_DEVICE_TABLE(spi, adau1781_spi_id);
+#if defined(CONFIG_OF)
+static const struct of_device_id adau1781_spi_dt_ids[] = {
+ { .compatible = "adi,adau1381", },
+ { .compatible = "adi,adau1781", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, adau1781_spi_dt_ids);
+#endif
+
static struct spi_driver adau1781_spi_driver = {
.driver = {
.name = "adau1781",
+ .of_match_table = of_match_ptr(adau1781_spi_dt_ids),
},
.probe = adau1781_spi_probe,
.remove = adau1781_spi_remove,
diff --git a/sound/soc/codecs/adau1781.c b/sound/soc/codecs/adau1781.c
index fde9068..bc1bb56 100644
--- a/sound/soc/codecs/adau1781.c
+++ b/sound/soc/codecs/adau1781.c
@@ -1,5 +1,5 @@
/*
- * Driver for ADAU1781/ADAU1781 codec
+ * Driver for ADAU1381/ADAU1781 codec
*
* Copyright 2011-2013 Analog Devices Inc.
* Author: Lars-Peter Clausen <lars@metafoo.de>
diff --git a/sound/soc/codecs/ads117x.c b/sound/soc/codecs/ads117x.c
index 1222282..c5be1bd 100644
--- a/sound/soc/codecs/ads117x.c
+++ b/sound/soc/codecs/ads117x.c
@@ -20,6 +20,8 @@
#include <sound/initval.h>
#include <sound/soc.h>
+#include <linux/of.h>
+
#define ADS117X_RATES (SNDRV_PCM_RATE_8000_48000)
#define ADS117X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
@@ -75,9 +77,19 @@ static int ads117x_remove(struct platform_device *pdev)
return 0;
}
+#if defined(CONFIG_OF)
+static const struct of_device_id ads117x_dt_ids[] = {
+ { .compatible = "ti,ads1174" },
+ { .compatible = "ti,ads1178" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, ads117x_dt_ids);
+#endif
+
static struct platform_driver ads117x_codec_driver = {
.driver = {
.name = "ads117x-codec",
+ .of_match_table = of_match_ptr(ads117x_dt_ids),
},
.probe = ads117x_probe,
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c
index 9178531..92d22a0 100644
--- a/sound/soc/codecs/arizona.c
+++ b/sound/soc/codecs/arizona.c
@@ -1398,29 +1398,6 @@ static const int arizona_48k_bclk_rates[] = {
24576000,
};
-static const unsigned int arizona_48k_rates[] = {
- 12000,
- 24000,
- 48000,
- 96000,
- 192000,
- 384000,
- 768000,
- 4000,
- 8000,
- 16000,
- 32000,
- 64000,
- 128000,
- 256000,
- 512000,
-};
-
-static const struct snd_pcm_hw_constraint_list arizona_48k_constraint = {
- .count = ARRAY_SIZE(arizona_48k_rates),
- .list = arizona_48k_rates,
-};
-
static const int arizona_44k1_bclk_rates[] = {
-1,
44100,
@@ -1443,22 +1420,7 @@ static const int arizona_44k1_bclk_rates[] = {
22579200,
};
-static const unsigned int arizona_44k1_rates[] = {
- 11025,
- 22050,
- 44100,
- 88200,
- 176400,
- 352800,
- 705600,
-};
-
-static const struct snd_pcm_hw_constraint_list arizona_44k1_constraint = {
- .count = ARRAY_SIZE(arizona_44k1_rates),
- .list = arizona_44k1_rates,
-};
-
-static int arizona_sr_vals[] = {
+static const unsigned int arizona_sr_vals[] = {
0,
12000,
24000,
@@ -1485,13 +1447,21 @@ static int arizona_sr_vals[] = {
512000,
};
+#define ARIZONA_48K_RATE_MASK 0x0F003E
+#define ARIZONA_44K1_RATE_MASK 0x003E00
+#define ARIZONA_RATE_MASK (ARIZONA_48K_RATE_MASK | ARIZONA_44K1_RATE_MASK)
+
+static const struct snd_pcm_hw_constraint_list arizona_constraint = {
+ .count = ARRAY_SIZE(arizona_sr_vals),
+ .list = arizona_sr_vals,
+};
+
static int arizona_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_codec *codec = dai->codec;
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
- const struct snd_pcm_hw_constraint_list *constraint;
unsigned int base_rate;
if (!substream->runtime)
@@ -1509,16 +1479,15 @@ static int arizona_startup(struct snd_pcm_substream *substream,
}
if (base_rate == 0)
- return 0;
-
- if (base_rate % 8000)
- constraint = &arizona_44k1_constraint;
+ dai_priv->constraint.mask = ARIZONA_RATE_MASK;
+ else if (base_rate % 8000)
+ dai_priv->constraint.mask = ARIZONA_44K1_RATE_MASK;
else
- constraint = &arizona_48k_constraint;
+ dai_priv->constraint.mask = ARIZONA_48K_RATE_MASK;
return snd_pcm_hw_constraint_list(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_RATE,
- constraint);
+ &dai_priv->constraint);
}
static void arizona_wm5102_set_dac_comp(struct snd_soc_codec *codec,
@@ -1911,6 +1880,7 @@ int arizona_init_dai(struct arizona_priv *priv, int id)
struct arizona_dai_priv *dai_priv = &priv->dai[id];
dai_priv->clk = ARIZONA_CLK_SYSCLK;
+ dai_priv->constraint = arizona_constraint;
return 0;
}
@@ -2179,11 +2149,12 @@ static int arizona_calc_fll(struct arizona_fll *fll,
return -EINVAL;
}
- arizona_fll_dbg(fll, "N=%x THETA=%x LAMBDA=%x\n",
+ arizona_fll_dbg(fll, "N=%d THETA=%d LAMBDA=%d\n",
cfg->n, cfg->theta, cfg->lambda);
- arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n",
- cfg->fratio, cfg->fratio, cfg->outdiv, cfg->refdiv);
- arizona_fll_dbg(fll, "GAIN=%d\n", cfg->gain);
+ arizona_fll_dbg(fll, "FRATIO=0x%x(%d) OUTDIV=%d REFCLK_DIV=0x%x(%d)\n",
+ cfg->fratio, ratio, cfg->outdiv,
+ cfg->refdiv, 1 << cfg->refdiv);
+ arizona_fll_dbg(fll, "GAIN=0x%x(%d)\n", cfg->gain, 1 << cfg->gain);
return 0;
diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h
index 8b6adb5..1ea8e4e 100644
--- a/sound/soc/codecs/arizona.h
+++ b/sound/soc/codecs/arizona.h
@@ -57,7 +57,7 @@
#define ARIZONA_CLK_98MHZ 5
#define ARIZONA_CLK_147MHZ 6
-#define ARIZONA_MAX_DAI 8
+#define ARIZONA_MAX_DAI 10
#define ARIZONA_MAX_ADSP 4
#define ARIZONA_DVFS_SR1_RQ 0x001
@@ -68,6 +68,8 @@ struct wm_adsp;
struct arizona_dai_priv {
int clk;
+
+ struct snd_pcm_hw_constraint_list constraint;
};
struct arizona_priv {
diff --git a/sound/soc/codecs/cs47l24.c b/sound/soc/codecs/cs47l24.c
index dc5ae7f..576087b 100644
--- a/sound/soc/codecs/cs47l24.c
+++ b/sound/soc/codecs/cs47l24.c
@@ -57,6 +57,25 @@ static const struct wm_adsp_region *cs47l24_dsp_regions[] = {
cs47l24_dsp3_regions,
};
+static int cs47l24_adsp_power_ev(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
+ unsigned int v;
+ int ret;
+
+ ret = regmap_read(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1, &v);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to read SYSCLK state: %d\n", ret);
+ return ret;
+ }
+
+ v = (v & ARIZONA_SYSCLK_FREQ_MASK) >> ARIZONA_SYSCLK_FREQ_SHIFT;
+
+ return wm_adsp2_early_event(w, kcontrol, event, v);
+}
+
static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0);
static DECLARE_TLV_DB_SCALE(noise_tlv, -13200, 600, 0);
@@ -405,8 +424,8 @@ SND_SOC_DAPM_PGA("ASRC2L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2L_ENA_SHIFT, 0,
SND_SOC_DAPM_PGA("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0,
NULL, 0),
-WM_ADSP2("DSP2", 1),
-WM_ADSP2("DSP3", 2),
+WM_ADSP2("DSP2", 1, cs47l24_adsp_power_ev),
+WM_ADSP2("DSP3", 2, cs47l24_adsp_power_ev),
SND_SOC_DAPM_PGA("ISRC1INT1", ARIZONA_ISRC_1_CTRL_3,
ARIZONA_ISRC1_INT0_ENA_SHIFT, 0, NULL, 0),
@@ -779,6 +798,9 @@ static const struct snd_soc_dapm_route cs47l24_dapm_routes[] = {
{ "AIF2 Capture", NULL, "SYSCLK" },
{ "AIF3 Capture", NULL, "SYSCLK" },
+ { "Voice Control DSP", NULL, "DSP3" },
+ { "Voice Control DSP", NULL, "SYSCLK" },
+
{ "IN1L PGA", NULL, "IN1L" },
{ "IN1R PGA", NULL, "IN1R" },
@@ -901,7 +923,7 @@ static int cs47l24_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
}
}
-#define CS47L24_RATES SNDRV_PCM_RATE_8000_192000
+#define CS47L24_RATES SNDRV_PCM_RATE_KNOT
#define CS47L24_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
@@ -973,12 +995,68 @@ static struct snd_soc_dai_driver cs47l24_dai[] = {
.symmetric_rates = 1,
.symmetric_samplebits = 1,
},
+ {
+ .name = "cs47l24-cpu-voicectrl",
+ .capture = {
+ .stream_name = "Voice Control CPU",
+ .channels_min = 1,
+ .channels_max = 1,
+ .rates = CS47L24_RATES,
+ .formats = CS47L24_FORMATS,
+ },
+ .compress_new = snd_soc_new_compress,
+ },
+ {
+ .name = "cs47l24-dsp-voicectrl",
+ .capture = {
+ .stream_name = "Voice Control DSP",
+ .channels_min = 1,
+ .channels_max = 1,
+ .rates = CS47L24_RATES,
+ .formats = CS47L24_FORMATS,
+ },
+ },
};
+static int cs47l24_open(struct snd_compr_stream *stream)
+{
+ struct snd_soc_pcm_runtime *rtd = stream->private_data;
+ struct cs47l24_priv *priv = snd_soc_codec_get_drvdata(rtd->codec);
+ struct arizona *arizona = priv->core.arizona;
+ int n_adsp;
+
+ if (strcmp(rtd->codec_dai->name, "cs47l24-dsp-voicectrl") == 0) {
+ n_adsp = 2;
+ } else {
+ dev_err(arizona->dev,
+ "No suitable compressed stream for DAI '%s'\n",
+ rtd->codec_dai->name);
+ return -EINVAL;
+ }
+
+ return wm_adsp_compr_open(&priv->core.adsp[n_adsp], stream);
+}
+
+static irqreturn_t cs47l24_adsp2_irq(int irq, void *data)
+{
+ struct cs47l24_priv *priv = data;
+ struct arizona *arizona = priv->core.arizona;
+ int ret;
+
+ ret = wm_adsp_compr_handle_irq(&priv->core.adsp[2]);
+ if (ret == -ENODEV) {
+ dev_err(arizona->dev, "Spurious compressed data IRQ\n");
+ return IRQ_NONE;
+ }
+
+ return IRQ_HANDLED;
+}
+
static int cs47l24_codec_probe(struct snd_soc_codec *codec)
{
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
struct cs47l24_priv *priv = snd_soc_codec_get_drvdata(codec);
+ struct arizona *arizona = priv->core.arizona;
int ret;
priv->core.arizona->dapm = dapm;
@@ -987,6 +1065,14 @@ static int cs47l24_codec_probe(struct snd_soc_codec *codec)
arizona_init_gpio(codec);
arizona_init_mono(codec);
+ ret = arizona_request_irq(arizona, ARIZONA_IRQ_DSP_IRQ1,
+ "ADSP2 Compressed IRQ", cs47l24_adsp2_irq,
+ priv);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to request DSP IRQ: %d\n", ret);
+ return ret;
+ }
+
ret = wm_adsp2_codec_probe(&priv->core.adsp[1], codec);
if (ret)
goto err_adsp2_codec_probe;
@@ -1014,13 +1100,14 @@ err_adsp2_codec_probe:
static int cs47l24_codec_remove(struct snd_soc_codec *codec)
{
struct cs47l24_priv *priv = snd_soc_codec_get_drvdata(codec);
-
+ struct arizona *arizona = priv->core.arizona;
wm_adsp2_codec_remove(&priv->core.adsp[1], codec);
wm_adsp2_codec_remove(&priv->core.adsp[2], codec);
priv->core.arizona->dapm = NULL;
+ arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, priv);
return 0;
}
@@ -1057,6 +1144,19 @@ static struct snd_soc_codec_driver soc_codec_dev_cs47l24 = {
.num_dapm_routes = ARRAY_SIZE(cs47l24_dapm_routes),
};
+static struct snd_compr_ops cs47l24_compr_ops = {
+ .open = cs47l24_open,
+ .free = wm_adsp_compr_free,
+ .set_params = wm_adsp_compr_set_params,
+ .get_caps = wm_adsp_compr_get_caps,
+ .trigger = wm_adsp_compr_trigger,
+ .pointer = wm_adsp_compr_pointer,
+ .copy = wm_adsp_compr_copy,
+};
+
+static struct snd_soc_platform_driver cs47l24_compr_platform = {
+ .compr_ops = &cs47l24_compr_ops,
+};
static int cs47l24_probe(struct platform_device *pdev)
{
struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
@@ -1120,12 +1220,25 @@ static int cs47l24_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
pm_runtime_idle(&pdev->dev);
- return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_cs47l24,
+ ret = snd_soc_register_platform(&pdev->dev, &cs47l24_compr_platform);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to register platform: %d\n", ret);
+ return ret;
+ }
+ ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_cs47l24,
cs47l24_dai, ARRAY_SIZE(cs47l24_dai));
+
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to register codec: %d\n", ret);
+ snd_soc_unregister_platform(&pdev->dev);
+ }
+
+ return ret;
}
static int cs47l24_remove(struct platform_device *pdev)
{
+ snd_soc_unregister_platform(&pdev->dev);
snd_soc_unregister_codec(&pdev->dev);
pm_runtime_disable(&pdev->dev);
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c
index 64637d1..a8b3e3f 100644
--- a/sound/soc/codecs/wm5102.c
+++ b/sound/soc/codecs/wm5102.c
@@ -619,7 +619,7 @@ static int wm5102_adsp_power_ev(struct snd_soc_dapm_widget *w,
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
- unsigned int v;
+ unsigned int v = 0;
int ret;
switch (event) {
@@ -654,7 +654,7 @@ static int wm5102_adsp_power_ev(struct snd_soc_dapm_widget *w,
break;
}
- return wm_adsp2_early_event(w, kcontrol, event);
+ return wm_adsp2_early_event(w, kcontrol, event, v);
}
static int wm5102_out_comp_coeff_get(struct snd_kcontrol *kcontrol,
@@ -1408,7 +1408,7 @@ ARIZONA_MUX_WIDGETS(ISRC2DEC2, "ISRC2DEC2"),
ARIZONA_MUX_WIDGETS(ISRC2INT1, "ISRC2INT1"),
ARIZONA_MUX_WIDGETS(ISRC2INT2, "ISRC2INT2"),
-WM_ADSP2_E("DSP1", 0, wm5102_adsp_power_ev),
+WM_ADSP2("DSP1", 0, wm5102_adsp_power_ev),
SND_SOC_DAPM_OUTPUT("HPOUT1L"),
SND_SOC_DAPM_OUTPUT("HPOUT1R"),
@@ -1599,6 +1599,9 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = {
{ "Slim2 Capture", NULL, "SYSCLK" },
{ "Slim3 Capture", NULL, "SYSCLK" },
+ { "Audio Trace DSP", NULL, "DSP1" },
+ { "Audio Trace DSP", NULL, "SYSCLK" },
+
{ "IN1L PGA", NULL, "IN1L" },
{ "IN1R PGA", NULL, "IN1R" },
@@ -1735,7 +1738,7 @@ static int wm5102_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
}
}
-#define WM5102_RATES SNDRV_PCM_RATE_8000_192000
+#define WM5102_RATES SNDRV_PCM_RATE_KNOT
#define WM5102_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
@@ -1864,14 +1867,67 @@ static struct snd_soc_dai_driver wm5102_dai[] = {
},
.ops = &arizona_simple_dai_ops,
},
+ {
+ .name = "wm5102-cpu-trace",
+ .capture = {
+ .stream_name = "Audio Trace CPU",
+ .channels_min = 1,
+ .channels_max = 6,
+ .rates = WM5102_RATES,
+ .formats = WM5102_FORMATS,
+ },
+ .compress_new = snd_soc_new_compress,
+ },
+ {
+ .name = "wm5102-dsp-trace",
+ .capture = {
+ .stream_name = "Audio Trace DSP",
+ .channels_min = 1,
+ .channels_max = 4,
+ .rates = WM5102_RATES,
+ .formats = WM5102_FORMATS,
+ },
+ },
};
+static int wm5102_open(struct snd_compr_stream *stream)
+{
+ struct snd_soc_pcm_runtime *rtd = stream->private_data;
+ struct wm5102_priv *priv = snd_soc_codec_get_drvdata(rtd->codec);
+
+ return wm_adsp_compr_open(&priv->core.adsp[0], stream);
+}
+
+static irqreturn_t wm5102_adsp2_irq(int irq, void *data)
+{
+ struct wm5102_priv *priv = data;
+ struct arizona *arizona = priv->core.arizona;
+ int ret;
+
+ ret = wm_adsp_compr_handle_irq(&priv->core.adsp[0]);
+ if (ret == -ENODEV) {
+ dev_err(arizona->dev, "Spurious compressed data IRQ\n");
+ return IRQ_NONE;
+ }
+
+ return IRQ_HANDLED;
+}
+
static int wm5102_codec_probe(struct snd_soc_codec *codec)
{
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec);
+ struct arizona *arizona = priv->core.arizona;
int ret;
+ ret = arizona_request_irq(arizona, ARIZONA_IRQ_DSP_IRQ1,
+ "ADSP2 Compressed IRQ", wm5102_adsp2_irq,
+ priv);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to request DSP IRQ: %d\n", ret);
+ return ret;
+ }
+
ret = wm_adsp2_codec_probe(&priv->core.adsp[0], codec);
if (ret)
return ret;
@@ -1946,6 +2002,20 @@ static struct snd_soc_codec_driver soc_codec_dev_wm5102 = {
.num_dapm_routes = ARRAY_SIZE(wm5102_dapm_routes),
};
+static struct snd_compr_ops wm5102_compr_ops = {
+ .open = wm5102_open,
+ .free = wm_adsp_compr_free,
+ .set_params = wm_adsp_compr_set_params,
+ .get_caps = wm_adsp_compr_get_caps,
+ .trigger = wm_adsp_compr_trigger,
+ .pointer = wm_adsp_compr_pointer,
+ .copy = wm_adsp_compr_copy,
+};
+
+static struct snd_soc_platform_driver wm5102_compr_platform = {
+ .compr_ops = &wm5102_compr_ops,
+};
+
static int wm5102_probe(struct platform_device *pdev)
{
struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
@@ -2005,12 +2075,25 @@ static int wm5102_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
pm_runtime_idle(&pdev->dev);
- return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm5102,
+ ret = snd_soc_register_platform(&pdev->dev, &wm5102_compr_platform);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to register platform: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm5102,
wm5102_dai, ARRAY_SIZE(wm5102_dai));
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to register codec: %d\n", ret);
+ snd_soc_unregister_platform(&pdev->dev);
+ }
+
+ return ret;
}
static int wm5102_remove(struct platform_device *pdev)
{
+ snd_soc_unregister_platform(&pdev->dev);
snd_soc_unregister_codec(&pdev->dev);
pm_runtime_disable(&pdev->dev);
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c
index 97c0f1e..83ba70f 100644
--- a/sound/soc/codecs/wm5110.c
+++ b/sound/soc/codecs/wm5110.c
@@ -191,6 +191,25 @@ static int wm5110_sysclk_ev(struct snd_soc_dapm_widget *w,
return 0;
}
+static int wm5110_adsp_power_ev(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
+ unsigned int v;
+ int ret;
+
+ ret = regmap_read(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1, &v);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to read SYSCLK state: %d\n", ret);
+ return ret;
+ }
+
+ v = (v & ARIZONA_SYSCLK_FREQ_MASK) >> ARIZONA_SYSCLK_FREQ_SHIFT;
+
+ return wm_adsp2_early_event(w, kcontrol, event, v);
+}
+
static const struct reg_sequence wm5110_no_dre_left_enable[] = {
{ 0x3024, 0xE410 },
{ 0x3025, 0x0056 },
@@ -1179,10 +1198,10 @@ SND_SOC_DAPM_PGA("ASRC2L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2L_ENA_SHIFT, 0,
SND_SOC_DAPM_PGA("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0,
NULL, 0),
-WM_ADSP2("DSP1", 0),
-WM_ADSP2("DSP2", 1),
-WM_ADSP2("DSP3", 2),
-WM_ADSP2("DSP4", 3),
+WM_ADSP2("DSP1", 0, wm5110_adsp_power_ev),
+WM_ADSP2("DSP2", 1, wm5110_adsp_power_ev),
+WM_ADSP2("DSP3", 2, wm5110_adsp_power_ev),
+WM_ADSP2("DSP4", 3, wm5110_adsp_power_ev),
SND_SOC_DAPM_PGA("ISRC1INT1", ARIZONA_ISRC_1_CTRL_3,
ARIZONA_ISRC1_INT0_ENA_SHIFT, 0, NULL, 0),
@@ -1809,6 +1828,9 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
{ "Voice Control DSP", NULL, "DSP3" },
{ "Voice Control DSP", NULL, "SYSCLK" },
+ { "Audio Trace DSP", NULL, "DSP1" },
+ { "Audio Trace DSP", NULL, "SYSCLK" },
+
{ "IN1L PGA", NULL, "IN1L" },
{ "IN1R PGA", NULL, "IN1R" },
@@ -2002,7 +2024,7 @@ static int wm5110_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
}
}
-#define WM5110_RATES SNDRV_PCM_RATE_8000_192000
+#define WM5110_RATES SNDRV_PCM_RATE_KNOT
#define WM5110_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
@@ -2152,6 +2174,27 @@ static struct snd_soc_dai_driver wm5110_dai[] = {
.formats = WM5110_FORMATS,
},
},
+ {
+ .name = "wm5110-cpu-trace",
+ .capture = {
+ .stream_name = "Audio Trace CPU",
+ .channels_min = 1,
+ .channels_max = 6,
+ .rates = WM5110_RATES,
+ .formats = WM5110_FORMATS,
+ },
+ .compress_new = snd_soc_new_compress,
+ },
+ {
+ .name = "wm5110-dsp-trace",
+ .capture = {
+ .stream_name = "Audio Trace DSP",
+ .channels_min = 1,
+ .channels_max = 6,
+ .rates = WM5110_RATES,
+ .formats = WM5110_FORMATS,
+ },
+ },
};
static int wm5110_open(struct snd_compr_stream *stream)
@@ -2163,6 +2206,8 @@ static int wm5110_open(struct snd_compr_stream *stream)
if (strcmp(rtd->codec_dai->name, "wm5110-dsp-voicectrl") == 0) {
n_adsp = 2;
+ } else if (strcmp(rtd->codec_dai->name, "wm5110-dsp-trace") == 0) {
+ n_adsp = 0;
} else {
dev_err(arizona->dev,
"No suitable compressed stream for DAI '%s'\n",
@@ -2175,12 +2220,21 @@ static int wm5110_open(struct snd_compr_stream *stream)
static irqreturn_t wm5110_adsp2_irq(int irq, void *data)
{
- struct wm5110_priv *florida = data;
- int ret;
+ struct wm5110_priv *priv = data;
+ struct arizona *arizona = priv->core.arizona;
+ int serviced = 0;
+ int i, ret;
- ret = wm_adsp_compr_handle_irq(&florida->core.adsp[2]);
- if (ret == -ENODEV)
+ for (i = 0; i < WM5110_NUM_ADSP; ++i) {
+ ret = wm_adsp_compr_handle_irq(&priv->core.adsp[i]);
+ if (ret != -ENODEV)
+ serviced++;
+ }
+
+ if (!serviced) {
+ dev_err(arizona->dev, "Spurious compressed data IRQ\n");
return IRQ_NONE;
+ }
return IRQ_HANDLED;
}
@@ -2366,7 +2420,7 @@ static int wm5110_probe(struct platform_device *pdev)
ret = snd_soc_register_platform(&pdev->dev, &wm5110_compr_platform);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to register platform: %d\n", ret);
- goto error;
+ return ret;
}
ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm5110,
@@ -2376,7 +2430,6 @@ static int wm5110_probe(struct platform_device *pdev)
snd_soc_unregister_platform(&pdev->dev);
}
-error:
return ret;
}
diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c
index b4dba3a..52d766e 100644
--- a/sound/soc/codecs/wm8997.c
+++ b/sound/soc/codecs/wm8997.c
@@ -943,7 +943,7 @@ static int wm8997_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
}
}
-#define WM8997_RATES SNDRV_PCM_RATE_8000_192000
+#define WM8997_RATES SNDRV_PCM_RATE_KNOT
#define WM8997_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
diff --git a/sound/soc/codecs/wm8998.c b/sound/soc/codecs/wm8998.c
index 7719bc5..0123960 100644
--- a/sound/soc/codecs/wm8998.c
+++ b/sound/soc/codecs/wm8998.c
@@ -1170,7 +1170,7 @@ static const struct snd_soc_dapm_route wm8998_dapm_routes[] = {
{ "DRC1 Signal Activity", NULL, "DRC1R" },
};
-#define WM8998_RATES SNDRV_PCM_RATE_8000_192000
+#define WM8998_RATES SNDRV_PCM_RATE_KNOT
#define WM8998_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index b9195b9..d3b1cb1 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -32,9 +32,6 @@
#include <sound/initval.h>
#include <sound/tlv.h>
-#include <linux/mfd/arizona/registers.h>
-
-#include "arizona.h"
#include "wm_adsp.h"
#define adsp_crit(_dsp, fmt, ...) \
@@ -295,6 +292,8 @@ struct wm_adsp_compr {
u32 *raw_buf;
unsigned int copied_total;
+
+ unsigned int sample_rate;
};
#define WM_ADSP_DATA_WORD_SIZE 3
@@ -328,7 +327,7 @@ struct wm_adsp_buffer_region_def {
unsigned int size_offset;
};
-static struct wm_adsp_buffer_region_def ez2control_regions[] = {
+static const struct wm_adsp_buffer_region_def default_regions[] = {
{
.mem_type = WMFW_ADSP2_XM,
.base_offset = HOST_BUFFER_FIELD(X_buf_base),
@@ -350,10 +349,10 @@ struct wm_adsp_fw_caps {
u32 id;
struct snd_codec_desc desc;
int num_regions;
- struct wm_adsp_buffer_region_def *region_defs;
+ const struct wm_adsp_buffer_region_def *region_defs;
};
-static const struct wm_adsp_fw_caps ez2control_caps[] = {
+static const struct wm_adsp_fw_caps ctrl_caps[] = {
{
.id = SND_AUDIOCODEC_BESPOKE,
.desc = {
@@ -362,8 +361,26 @@ static const struct wm_adsp_fw_caps ez2control_caps[] = {
.num_sample_rates = 1,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
},
- .num_regions = ARRAY_SIZE(ez2control_regions),
- .region_defs = ez2control_regions,
+ .num_regions = ARRAY_SIZE(default_regions),
+ .region_defs = default_regions,
+ },
+};
+
+static const struct wm_adsp_fw_caps trace_caps[] = {
+ {
+ .id = SND_AUDIOCODEC_BESPOKE,
+ .desc = {
+ .max_ch = 8,
+ .sample_rates = {
+ 4000, 8000, 11025, 12000, 16000, 22050,
+ 24000, 32000, 44100, 48000, 64000, 88200,
+ 96000, 176400, 192000
+ },
+ .num_sample_rates = 15,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+ .num_regions = ARRAY_SIZE(default_regions),
+ .region_defs = default_regions,
},
};
@@ -382,11 +399,16 @@ static const struct {
[WM_ADSP_FW_CTRL] = {
.file = "ctrl",
.compr_direction = SND_COMPRESS_CAPTURE,
- .num_caps = ARRAY_SIZE(ez2control_caps),
- .caps = ez2control_caps,
+ .num_caps = ARRAY_SIZE(ctrl_caps),
+ .caps = ctrl_caps,
},
[WM_ADSP_FW_ASR] = { .file = "asr" },
- [WM_ADSP_FW_TRACE] = { .file = "trace" },
+ [WM_ADSP_FW_TRACE] = {
+ .file = "trace",
+ .compr_direction = SND_COMPRESS_CAPTURE,
+ .num_caps = ARRAY_SIZE(trace_caps),
+ .caps = trace_caps,
+ },
[WM_ADSP_FW_SPK_PROT] = { .file = "spk-prot" },
[WM_ADSP_FW_MISC] = { .file = "misc" },
};
@@ -719,19 +741,19 @@ static int wm_coeff_write_control(struct wm_coeff_ctl *ctl,
reg = ctl->alg_region.base + ctl->offset;
reg = wm_adsp_region_to_reg(mem, reg);
- scratch = kmemdup(buf, ctl->len, GFP_KERNEL | GFP_DMA);
+ scratch = kmemdup(buf, len, GFP_KERNEL | GFP_DMA);
if (!scratch)
return -ENOMEM;
ret = regmap_raw_write(dsp->regmap, reg, scratch,
- ctl->len);
+ len);
if (ret) {
adsp_err(dsp, "Failed to write %zu bytes to %x: %d\n",
- ctl->len, reg, ret);
+ len, reg, ret);
kfree(scratch);
return ret;
}
- adsp_dbg(dsp, "Wrote %zu bytes to %x\n", ctl->len, reg);
+ adsp_dbg(dsp, "Wrote %zu bytes to %x\n", len, reg);
kfree(scratch);
@@ -778,20 +800,20 @@ static int wm_coeff_read_control(struct wm_coeff_ctl *ctl,
reg = ctl->alg_region.base + ctl->offset;
reg = wm_adsp_region_to_reg(mem, reg);
- scratch = kmalloc(ctl->len, GFP_KERNEL | GFP_DMA);
+ scratch = kmalloc(len, GFP_KERNEL | GFP_DMA);
if (!scratch)
return -ENOMEM;
- ret = regmap_raw_read(dsp->regmap, reg, scratch, ctl->len);
+ ret = regmap_raw_read(dsp->regmap, reg, scratch, len);
if (ret) {
adsp_err(dsp, "Failed to read %zu bytes from %x: %d\n",
- ctl->len, reg, ret);
+ len, reg, ret);
kfree(scratch);
return ret;
}
- adsp_dbg(dsp, "Read %zu bytes from %x\n", ctl->len, reg);
+ adsp_dbg(dsp, "Read %zu bytes from %x\n", len, reg);
- memcpy(buf, scratch, ctl->len);
+ memcpy(buf, scratch, len);
kfree(scratch);
return 0;
@@ -855,17 +877,18 @@ static int wmfw_add_ctl(struct wm_adsp *dsp, struct wm_coeff_ctl *ctl)
kcontrol->access |= SNDRV_CTL_ELEM_ACCESS_READ;
if (ctl->flags & WMFW_CTL_FLAG_VOLATILE)
kcontrol->access |= SNDRV_CTL_ELEM_ACCESS_VOLATILE;
+ } else {
+ kcontrol->access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
+ kcontrol->access |= SNDRV_CTL_ELEM_ACCESS_VOLATILE;
}
- ret = snd_soc_add_card_controls(dsp->card,
- kcontrol, 1);
+ ret = snd_soc_add_card_controls(dsp->card, kcontrol, 1);
if (ret < 0)
goto err_kcontrol;
kfree(kcontrol);
- ctl->kcontrol = snd_soc_card_get_kcontrol(dsp->card,
- ctl->name);
+ ctl->kcontrol = snd_soc_card_get_kcontrol(dsp->card, ctl->name);
return 0;
@@ -885,9 +908,7 @@ static int wm_coeff_init_control_caches(struct wm_adsp *dsp)
if (ctl->flags & WMFW_CTL_FLAG_VOLATILE)
continue;
- ret = wm_coeff_read_control(ctl,
- ctl->cache,
- ctl->len);
+ ret = wm_coeff_read_control(ctl, ctl->cache, ctl->len);
if (ret < 0)
return ret;
}
@@ -904,9 +925,7 @@ static int wm_coeff_sync_controls(struct wm_adsp *dsp)
if (!ctl->enabled)
continue;
if (ctl->set && !(ctl->flags & WMFW_CTL_FLAG_VOLATILE)) {
- ret = wm_coeff_write_control(ctl,
- ctl->cache,
- ctl->len);
+ ret = wm_coeff_write_control(ctl, ctl->cache, ctl->len);
if (ret < 0)
return ret;
}
@@ -1502,8 +1521,7 @@ static void *wm_adsp_read_algs(struct wm_adsp *dsp, size_t n_algs,
ret = regmap_raw_read(dsp->regmap, pos, alg, len * 2);
if (ret != 0) {
- adsp_err(dsp, "Failed to read algorithm list: %d\n",
- ret);
+ adsp_err(dsp, "Failed to read algorithm list: %d\n", ret);
kfree(alg);
return ERR_PTR(ret);
}
@@ -2002,8 +2020,7 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
goto err_mutex;
}
- val = (val & dsp->sysclk_mask)
- >> dsp->sysclk_shift;
+ val = (val & dsp->sysclk_mask) >> dsp->sysclk_shift;
ret = regmap_update_bits(dsp->regmap,
dsp->base + ADSP1_CONTROL_31,
@@ -2096,8 +2113,7 @@ static int wm_adsp2_ena(struct wm_adsp *dsp)
/* Wait for the RAM to start, should be near instantaneous */
for (count = 0; count < 10; ++count) {
- ret = regmap_read(dsp->regmap, dsp->base + ADSP2_STATUS1,
- &val);
+ ret = regmap_read(dsp->regmap, dsp->base + ADSP2_STATUS1, &val);
if (ret != 0)
return ret;
@@ -2123,30 +2139,9 @@ static void wm_adsp2_boot_work(struct work_struct *work)
struct wm_adsp,
boot_work);
int ret;
- unsigned int val;
mutex_lock(&dsp->pwr_lock);
- /*
- * For simplicity set the DSP clock rate to be the
- * SYSCLK rate rather than making it configurable.
- */
- ret = regmap_read(dsp->regmap, ARIZONA_SYSTEM_CLOCK_1, &val);
- if (ret != 0) {
- adsp_err(dsp, "Failed to read SYSCLK state: %d\n", ret);
- goto err_mutex;
- }
- val = (val & ARIZONA_SYSCLK_FREQ_MASK)
- >> ARIZONA_SYSCLK_FREQ_SHIFT;
-
- ret = regmap_update_bits_async(dsp->regmap,
- dsp->base + ADSP2_CLOCKING,
- ADSP2_CLK_SEL_MASK, val);
- if (ret != 0) {
- adsp_err(dsp, "Failed to set clock rate: %d\n", ret);
- goto err_mutex;
- }
-
ret = wm_adsp2_ena(dsp);
if (ret != 0)
goto err_mutex;
@@ -2186,8 +2181,21 @@ err_mutex:
mutex_unlock(&dsp->pwr_lock);
}
+static void wm_adsp2_set_dspclk(struct wm_adsp *dsp, unsigned int freq)
+{
+ int ret;
+
+ ret = regmap_update_bits_async(dsp->regmap,
+ dsp->base + ADSP2_CLOCKING,
+ ADSP2_CLK_SEL_MASK,
+ freq << ADSP2_CLK_SEL_SHIFT);
+ if (ret != 0)
+ adsp_err(dsp, "Failed to set clock rate: %d\n", ret);
+}
+
int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event)
+ struct snd_kcontrol *kcontrol, int event,
+ unsigned int freq)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
@@ -2197,6 +2205,7 @@ int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
+ wm_adsp2_set_dspclk(dsp, freq);
queue_work(system_unbound_wq, &dsp->boot_work);
break;
default:
@@ -2471,6 +2480,8 @@ int wm_adsp_compr_set_params(struct snd_compr_stream *stream,
if (!compr->raw_buf)
return -ENOMEM;
+ compr->sample_rate = params->codec.sample_rate;
+
return 0;
}
EXPORT_SYMBOL_GPL(wm_adsp_compr_set_params);
@@ -2810,7 +2821,6 @@ int wm_adsp_compr_handle_irq(struct wm_adsp *dsp)
mutex_lock(&dsp->pwr_lock);
if (!buf) {
- adsp_err(dsp, "Spurious buffer IRQ\n");
ret = -ENODEV;
goto out;
}
@@ -2841,7 +2851,7 @@ int wm_adsp_compr_handle_irq(struct wm_adsp *dsp)
goto out;
}
- if (compr->stream)
+ if (compr && compr->stream)
snd_compr_fragment_elapsed(compr->stream);
out:
@@ -2911,6 +2921,7 @@ int wm_adsp_compr_pointer(struct snd_compr_stream *stream,
tstamp->copied_total = compr->copied_total;
tstamp->copied_total += buf->avail * WM_ADSP_DATA_WORD_SIZE;
+ tstamp->sampling_rate = compr->sample_rate;
out:
mutex_unlock(&dsp->pwr_lock);
diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h
index 1a928ec..b61cb57 100644
--- a/sound/soc/codecs/wm_adsp.h
+++ b/sound/soc/codecs/wm_adsp.h
@@ -80,7 +80,7 @@ struct wm_adsp {
SND_SOC_DAPM_PGA_E(wname, SND_SOC_NOPM, num, 0, NULL, 0, \
wm_adsp1_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD)
-#define WM_ADSP2_E(wname, num, event_fn) \
+#define WM_ADSP2(wname, num, event_fn) \
{ .id = snd_soc_dapm_dai_link, .name = wname " Preloader", \
.reg = SND_SOC_NOPM, .shift = num, .event = event_fn, \
.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD }, \
@@ -88,9 +88,6 @@ struct wm_adsp {
.reg = SND_SOC_NOPM, .shift = num, .event = wm_adsp2_event, \
.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD }
-#define WM_ADSP2(wname, num) \
- WM_ADSP2_E(wname, num, wm_adsp2_early_event)
-
extern const struct snd_kcontrol_new wm_adsp_fw_controls[];
int wm_adsp1_init(struct wm_adsp *dsp);
@@ -100,7 +97,8 @@ int wm_adsp2_codec_remove(struct wm_adsp *dsp, struct snd_soc_codec *codec);
int wm_adsp1_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event);
int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event);
+ struct snd_kcontrol *kcontrol, int event,
+ unsigned int freq);
int wm_adsp2_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event);