diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index ffc89fab96fbf4b6ccc81973f69df863132da1ec..990403b162feeb35de717578b0ef27529d223abb 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -350,6 +350,141 @@ static int wm_adsp_load(struct wm_adsp *dsp)
 	return ret;
 }
 
+static int wm_adsp_setup_algs(struct wm_adsp *dsp)
+{
+	struct regmap *regmap = dsp->regmap;
+	struct wmfw_adsp1_id_hdr adsp1_id;
+	struct wmfw_adsp2_id_hdr adsp2_id;
+	struct wmfw_adsp1_alg_hdr *adsp1_alg;
+	struct wmfw_adsp2_alg_hdr *adsp2_alg;
+	void *alg;
+	const struct wm_adsp_region *mem;
+	unsigned int pos, term;
+	size_t algs;
+	__be32 val;
+	int i, ret;
+
+	switch (dsp->type) {
+	case WMFW_ADSP1:
+		mem = wm_adsp_find_region(dsp, WMFW_ADSP1_DM);
+		break;
+	case WMFW_ADSP2:
+		mem = wm_adsp_find_region(dsp, WMFW_ADSP2_XM);
+		break;
+	default:
+		mem = NULL;
+		break;
+	}
+
+	if (mem == NULL) {
+		BUG_ON(mem != NULL);
+		return -EINVAL;
+	}
+
+	switch (dsp->type) {
+	case WMFW_ADSP1:
+		ret = regmap_raw_read(regmap, mem->base, &adsp1_id,
+				      sizeof(adsp1_id));
+		if (ret != 0) {
+			adsp_err(dsp, "Failed to read algorithm info: %d\n",
+				 ret);
+			return ret;
+		}
+
+		algs = be32_to_cpu(adsp1_id.algs);
+		adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n",
+			  be32_to_cpu(adsp1_id.fw.id),
+			  (be32_to_cpu(adsp1_id.fw.ver) & 0xff0000) >> 16,
+			  (be32_to_cpu(adsp1_id.fw.ver) & 0xff00) >> 8,
+			  be32_to_cpu(adsp1_id.fw.ver) & 0xff,
+			  algs);
+
+		pos = sizeof(adsp1_id) / 2;
+		term = pos + ((sizeof(*adsp1_alg) * algs) / 2);
+		break;
+
+	case WMFW_ADSP2:
+		ret = regmap_raw_read(regmap, mem->base, &adsp2_id,
+				      sizeof(adsp2_id));
+		if (ret != 0) {
+			adsp_err(dsp, "Failed to read algorithm info: %d\n",
+				 ret);
+			return ret;
+		}
+
+		algs = be32_to_cpu(adsp2_id.algs);
+		adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n",
+			  be32_to_cpu(adsp2_id.fw.id),
+			  (be32_to_cpu(adsp2_id.fw.ver) & 0xff0000) >> 16,
+			  (be32_to_cpu(adsp2_id.fw.ver) & 0xff00) >> 8,
+			  be32_to_cpu(adsp2_id.fw.ver) & 0xff,
+			  algs);
+
+		pos = sizeof(adsp2_id) / 2;
+		term = pos + ((sizeof(*adsp2_alg) * algs) / 2);
+		break;
+
+	default:
+		BUG_ON(NULL == "Unknown DSP type");
+		return -EINVAL;
+	}
+
+	if (algs == 0) {
+		adsp_err(dsp, "No algorithms\n");
+		return -EINVAL;
+	}
+
+	/* Read the terminator first to validate the length */
+	ret = regmap_raw_read(regmap, mem->base + term, &val, sizeof(val));
+	if (ret != 0) {
+		adsp_err(dsp, "Failed to read algorithm list end: %d\n",
+			ret);
+		return ret;
+	}
+
+	if (be32_to_cpu(val) != 0xbedead)
+		adsp_warn(dsp, "Algorithm list end %x 0x%x != 0xbeadead\n",
+			  term, be32_to_cpu(val));
+
+	alg = kzalloc((term - pos) * 2, GFP_KERNEL);
+	if (!alg)
+		return -ENOMEM;
+
+	ret = regmap_raw_read(regmap, mem->base + pos, alg, (term - pos) * 2);
+	if (ret != 0) {
+		adsp_err(dsp, "Failed to read algorithm list: %d\n",
+			ret);
+		goto out;
+	}
+
+	adsp1_alg = alg;
+	adsp2_alg = alg;
+
+	for (i = 0; i < algs; i++) {
+		switch (dsp->type) {
+		case WMFW_ADSP1:
+			adsp_info(dsp, "%d: ID %x v%d.%d.%d\n",
+				  i, be32_to_cpu(adsp1_alg[i].alg.id),
+				  (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff0000) >> 16,
+				  (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff00) >> 8,
+				  be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff);
+			break;
+
+		case WMFW_ADSP2:
+			adsp_info(dsp, "%d: ID %x v%d.%d.%d\n",
+				  i, be32_to_cpu(adsp2_alg[i].alg.id),
+				  (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff0000) >> 16,
+				  (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff00) >> 8,
+				  be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff);
+			break;
+		}
+	}
+
+out:
+	kfree(alg);
+	return ret;
+}
+
 static int wm_adsp_load_coeff(struct wm_adsp *dsp)
 {
 	struct regmap *regmap = dsp->regmap;
@@ -468,6 +603,10 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
 		if (ret != 0)
 			goto err;
 
+		ret = wm_adsp_setup_algs(dsp);
+		if (ret != 0)
+			goto err;
+
 		ret = wm_adsp_load_coeff(dsp);
 		if (ret != 0)
 			goto err;
@@ -604,6 +743,10 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
 		if (ret != 0)
 			goto err;
 
+		ret = wm_adsp_setup_algs(dsp);
+		if (ret != 0)
+			goto err;
+
 		ret = wm_adsp_load_coeff(dsp);
 		if (ret != 0)
 			goto err;