aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/codecs/wm_adsp.c143
1 files changed, 143 insertions, 0 deletions
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index ffc89fab96fb..990403b162fe 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -350,6 +350,141 @@ out:
350 return ret; 350 return ret;
351} 351}
352 352
353static int wm_adsp_setup_algs(struct wm_adsp *dsp)
354{
355 struct regmap *regmap = dsp->regmap;
356 struct wmfw_adsp1_id_hdr adsp1_id;
357 struct wmfw_adsp2_id_hdr adsp2_id;
358 struct wmfw_adsp1_alg_hdr *adsp1_alg;
359 struct wmfw_adsp2_alg_hdr *adsp2_alg;
360 void *alg;
361 const struct wm_adsp_region *mem;
362 unsigned int pos, term;
363 size_t algs;
364 __be32 val;
365 int i, ret;
366
367 switch (dsp->type) {
368 case WMFW_ADSP1:
369 mem = wm_adsp_find_region(dsp, WMFW_ADSP1_DM);
370 break;
371 case WMFW_ADSP2:
372 mem = wm_adsp_find_region(dsp, WMFW_ADSP2_XM);
373 break;
374 default:
375 mem = NULL;
376 break;
377 }
378
379 if (mem == NULL) {
380 BUG_ON(mem != NULL);
381 return -EINVAL;
382 }
383
384 switch (dsp->type) {
385 case WMFW_ADSP1:
386 ret = regmap_raw_read(regmap, mem->base, &adsp1_id,
387 sizeof(adsp1_id));
388 if (ret != 0) {
389 adsp_err(dsp, "Failed to read algorithm info: %d\n",
390 ret);
391 return ret;
392 }
393
394 algs = be32_to_cpu(adsp1_id.algs);
395 adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n",
396 be32_to_cpu(adsp1_id.fw.id),
397 (be32_to_cpu(adsp1_id.fw.ver) & 0xff0000) >> 16,
398 (be32_to_cpu(adsp1_id.fw.ver) & 0xff00) >> 8,
399 be32_to_cpu(adsp1_id.fw.ver) & 0xff,
400 algs);
401
402 pos = sizeof(adsp1_id) / 2;
403 term = pos + ((sizeof(*adsp1_alg) * algs) / 2);
404 break;
405
406 case WMFW_ADSP2:
407 ret = regmap_raw_read(regmap, mem->base, &adsp2_id,
408 sizeof(adsp2_id));
409 if (ret != 0) {
410 adsp_err(dsp, "Failed to read algorithm info: %d\n",
411 ret);
412 return ret;
413 }
414
415 algs = be32_to_cpu(adsp2_id.algs);
416 adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n",
417 be32_to_cpu(adsp2_id.fw.id),
418 (be32_to_cpu(adsp2_id.fw.ver) & 0xff0000) >> 16,
419 (be32_to_cpu(adsp2_id.fw.ver) & 0xff00) >> 8,
420 be32_to_cpu(adsp2_id.fw.ver) & 0xff,
421 algs);
422
423 pos = sizeof(adsp2_id) / 2;
424 term = pos + ((sizeof(*adsp2_alg) * algs) / 2);
425 break;
426
427 default:
428 BUG_ON(NULL == "Unknown DSP type");
429 return -EINVAL;
430 }
431
432 if (algs == 0) {
433 adsp_err(dsp, "No algorithms\n");
434 return -EINVAL;
435 }
436
437 /* Read the terminator first to validate the length */
438 ret = regmap_raw_read(regmap, mem->base + term, &val, sizeof(val));
439 if (ret != 0) {
440 adsp_err(dsp, "Failed to read algorithm list end: %d\n",
441 ret);
442 return ret;
443 }
444
445 if (be32_to_cpu(val) != 0xbedead)
446 adsp_warn(dsp, "Algorithm list end %x 0x%x != 0xbeadead\n",
447 term, be32_to_cpu(val));
448
449 alg = kzalloc((term - pos) * 2, GFP_KERNEL);
450 if (!alg)
451 return -ENOMEM;
452
453 ret = regmap_raw_read(regmap, mem->base + pos, alg, (term - pos) * 2);
454 if (ret != 0) {
455 adsp_err(dsp, "Failed to read algorithm list: %d\n",
456 ret);
457 goto out;
458 }
459
460 adsp1_alg = alg;
461 adsp2_alg = alg;
462
463 for (i = 0; i < algs; i++) {
464 switch (dsp->type) {
465 case WMFW_ADSP1:
466 adsp_info(dsp, "%d: ID %x v%d.%d.%d\n",
467 i, be32_to_cpu(adsp1_alg[i].alg.id),
468 (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff0000) >> 16,
469 (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff00) >> 8,
470 be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff);
471 break;
472
473 case WMFW_ADSP2:
474 adsp_info(dsp, "%d: ID %x v%d.%d.%d\n",
475 i, be32_to_cpu(adsp2_alg[i].alg.id),
476 (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff0000) >> 16,
477 (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff00) >> 8,
478 be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff);
479 break;
480 }
481 }
482
483out:
484 kfree(alg);
485 return ret;
486}
487
353static int wm_adsp_load_coeff(struct wm_adsp *dsp) 488static int wm_adsp_load_coeff(struct wm_adsp *dsp)
354{ 489{
355 struct regmap *regmap = dsp->regmap; 490 struct regmap *regmap = dsp->regmap;
@@ -468,6 +603,10 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
468 if (ret != 0) 603 if (ret != 0)
469 goto err; 604 goto err;
470 605
606 ret = wm_adsp_setup_algs(dsp);
607 if (ret != 0)
608 goto err;
609
471 ret = wm_adsp_load_coeff(dsp); 610 ret = wm_adsp_load_coeff(dsp);
472 if (ret != 0) 611 if (ret != 0)
473 goto err; 612 goto err;
@@ -604,6 +743,10 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
604 if (ret != 0) 743 if (ret != 0)
605 goto err; 744 goto err;
606 745
746 ret = wm_adsp_setup_algs(dsp);
747 if (ret != 0)
748 goto err;
749
607 ret = wm_adsp_load_coeff(dsp); 750 ret = wm_adsp_load_coeff(dsp);
608 if (ret != 0) 751 if (ret != 0)
609 goto err; 752 goto err;