summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sound/soc/codecs/adau1761.c86
-rw-r--r--sound/soc/codecs/adau17x1.c20
-rw-r--r--sound/soc/codecs/adau17x1.h1
3 files changed, 99 insertions, 8 deletions
diff --git a/sound/soc/codecs/adau1761.c b/sound/soc/codecs/adau1761.c
index fb006fc81653..8f887227981f 100644
--- a/sound/soc/codecs/adau1761.c
+++ b/sound/soc/codecs/adau1761.c
@@ -556,8 +556,6 @@ static const struct snd_soc_dapm_route adau1761_dapm_routes[] = {
{ "Left DAC", NULL, "Interpolator Resync Clock" },
{ "Right DAC", NULL, "Interpolator Resync Clock" },
- { "DSP", NULL, "Digital Clock 0" },
-
{ "Slew Clock", NULL, "Digital Clock 0" },
{ "Right Playback Mixer", NULL, "Slew Clock" },
{ "Left Playback Mixer", NULL, "Slew Clock" },
@@ -569,6 +567,56 @@ static const struct snd_soc_dapm_route adau1761_dapm_routes[] = {
{ "Digital Clock 1", NULL, "SYSCLK" },
};
+static const struct snd_soc_dapm_route adau1761_dapm_dsp_routes[] = {
+ { "DSP", NULL, "Digital Clock 0" },
+};
+
+static int adau1761_compatibility_probe(struct device *dev)
+{
+ struct adau *adau = dev_get_drvdata(dev);
+ struct regmap *regmap = adau->regmap;
+ int val, ret = 0;
+
+ /* Only consider compatibility mode when ADAU1361 was specified. */
+ if (adau->type != ADAU1361)
+ return 0;
+
+ regcache_cache_bypass(regmap, true);
+
+ /*
+ * This will enable the core clock and bypass the PLL,
+ * so that we can access the registers for probing purposes
+ * (without having to set up the PLL).
+ */
+ regmap_write(regmap, ADAU17X1_CLOCK_CONTROL,
+ ADAU17X1_CLOCK_CONTROL_SYSCLK_EN);
+
+ /*
+ * ADAU17X1_SERIAL_SAMPLING_RATE doesn't exist in non-DSP chips;
+ * reading it results in zero at all times, and write is a no-op.
+ * Use this register to probe for ADAU1761.
+ */
+ regmap_write(regmap, ADAU17X1_SERIAL_SAMPLING_RATE, 1);
+ ret = regmap_read(regmap, ADAU17X1_SERIAL_SAMPLING_RATE, &val);
+ if (ret)
+ goto exit;
+ if (val != 1)
+ goto exit;
+ regmap_write(regmap, ADAU17X1_SERIAL_SAMPLING_RATE, 0);
+ ret = regmap_read(regmap, ADAU17X1_SERIAL_SAMPLING_RATE, &val);
+ if (ret)
+ goto exit;
+ if (val != 0)
+ goto exit;
+
+ adau->type = ADAU1761_AS_1361;
+exit:
+ /* Disable core clock after probing. */
+ regmap_write(regmap, ADAU17X1_CLOCK_CONTROL, 0);
+ regcache_cache_bypass(regmap, false);
+ return ret;
+}
+
static int adau1761_set_bias_level(struct snd_soc_component *component,
enum snd_soc_bias_level level)
{
@@ -823,7 +871,11 @@ static int adau1761_component_probe(struct snd_soc_component *component)
if (ret)
return ret;
- if (adau->type == ADAU1761) {
+ /*
+ * If we've got an ADAU1761, or an ADAU1761 operating as an
+ * ADAU1361, we need these non-DSP related DAPM widgets and routes.
+ */
+ if (adau->type == ADAU1761 || adau->type == ADAU1761_AS_1361) {
ret = snd_soc_dapm_new_controls(dapm, adau1761_dapm_widgets,
ARRAY_SIZE(adau1761_dapm_widgets));
if (ret)
@@ -834,7 +886,29 @@ static int adau1761_component_probe(struct snd_soc_component *component)
if (ret)
return ret;
}
-
+ /*
+ * These routes are DSP related and only used when we have a
+ * bona fide ADAU1761.
+ */
+ if (adau->type == ADAU1761) {
+ ret = snd_soc_dapm_add_routes(dapm, adau1761_dapm_dsp_routes,
+ ARRAY_SIZE(adau1761_dapm_dsp_routes));
+ if (ret)
+ return ret;
+ }
+ /*
+ * In the ADAU1761, by default, the AIF is routed to the DSP, whereas
+ * for the ADAU1361, the AIF is permanently routed to the ADC and DAC.
+ * Thus, if we have an ADAU1761 masquerading as an ADAU1361,
+ * we need to explicitly route the AIF to the ADC and DAC.
+ * For the ADAU1761, this is normally done by set_tdm_slot, but this
+ * function is not necessarily called during stream setup, so set up
+ * the compatible AIF routings here from the start.
+ */
+ if (adau->type == ADAU1761_AS_1361) {
+ regmap_write(adau->regmap, ADAU17X1_SERIAL_INPUT_ROUTE, 0x01);
+ regmap_write(adau->regmap, ADAU17X1_SERIAL_OUTPUT_ROUTE, 0x01);
+ }
ret = adau17x1_add_routes(component);
if (ret < 0)
return ret;
@@ -919,6 +993,10 @@ int adau1761_probe(struct device *dev, struct regmap *regmap,
if (ret)
return ret;
+ ret = adau1761_compatibility_probe(dev);
+ 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);
diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c
index af05463af4ac..c0f44ecef606 100644
--- a/sound/soc/codecs/adau17x1.c
+++ b/sound/soc/codecs/adau17x1.c
@@ -334,6 +334,17 @@ static bool adau17x1_has_dsp(struct adau *adau)
}
}
+/* Chip has a DSP but we're pretending it doesn't. */
+static bool adau17x1_has_disused_dsp(struct adau *adau)
+{
+ switch (adau->type) {
+ case ADAU1761_AS_1361:
+ return true;
+ default:
+ return false;
+ }
+}
+
static bool adau17x1_has_safeload(struct adau *adau)
{
switch (adau->type) {
@@ -516,10 +527,11 @@ static int adau17x1_hw_params(struct snd_pcm_substream *substream,
regmap_update_bits(adau->regmap, ADAU17X1_CONVERTER0,
ADAU17X1_CONVERTER0_CONVSR_MASK, div);
- if (adau17x1_has_dsp(adau)) {
+
+ if (adau17x1_has_dsp(adau) || adau17x1_has_disused_dsp(adau))
regmap_write(adau->regmap, ADAU17X1_SERIAL_SAMPLING_RATE, div);
+ if (adau17x1_has_dsp(adau))
regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, dsp_div);
- }
if (adau->sigmadsp) {
ret = adau17x1_setup_firmware(component, params_rate(params));
@@ -663,7 +675,7 @@ static int adau17x1_set_dai_tdm_slot(struct snd_soc_dai *dai,
switch (slot_width * slots) {
case 32:
- if (adau->type == ADAU1761)
+ if (adau->type == ADAU1761 || adau->type == ADAU1761_AS_1361)
return -EINVAL;
ser_ctrl1 = ADAU17X1_SERIAL_PORT1_BCLK32;
@@ -738,7 +750,7 @@ static int adau17x1_set_dai_tdm_slot(struct snd_soc_dai *dai,
regmap_update_bits(adau->regmap, ADAU17X1_SERIAL_PORT1,
ADAU17X1_SERIAL_PORT1_BCLK_MASK, ser_ctrl1);
- if (!adau17x1_has_dsp(adau))
+ if (!adau17x1_has_dsp(adau) && !adau17x1_has_disused_dsp(adau))
return 0;
if (adau->dsp_bypass[SNDRV_PCM_STREAM_PLAYBACK]) {
diff --git a/sound/soc/codecs/adau17x1.h b/sound/soc/codecs/adau17x1.h
index 98a3b6f5bc96..5e58abfffc3d 100644
--- a/sound/soc/codecs/adau17x1.h
+++ b/sound/soc/codecs/adau17x1.h
@@ -10,6 +10,7 @@
enum adau17x1_type {
ADAU1361,
ADAU1761,
+ ADAU1761_AS_1361,
ADAU1381,
ADAU1781,
};