aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2013-01-08 11:09:31 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2013-01-08 15:47:34 -0500
commit471f488583c62e4daca7d24fc7c937a39de7d95f (patch)
treec625d544d00426f091f30e16bda0cfc93efd7d44
parentd62f4bc665f3efd2a3d20134f874608b8afce7a1 (diff)
ASoC: wm_adsp: Implement support for algorithm-specific coefficient blocks
WMDR coefficient files can specify coefficients in terms of algorithm specific data regions. Record the start addresses of these regions while parsing the algorithms and then use them to handle coefficients with these formats. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r--sound/soc/codecs/wm_adsp.c114
-rw-r--r--sound/soc/codecs/wm_adsp.h9
2 files changed, 119 insertions, 4 deletions
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index 017d5101e789..5015ff287c39 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -378,6 +378,7 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp)
378 struct wmfw_adsp1_alg_hdr *adsp1_alg; 378 struct wmfw_adsp1_alg_hdr *adsp1_alg;
379 struct wmfw_adsp2_alg_hdr *adsp2_alg; 379 struct wmfw_adsp2_alg_hdr *adsp2_alg;
380 void *alg, *buf; 380 void *alg, *buf;
381 struct wm_adsp_alg_region *region;
381 const struct wm_adsp_region *mem; 382 const struct wm_adsp_region *mem;
382 unsigned int pos, term; 383 unsigned int pos, term;
383 size_t algs, buf_size; 384 size_t algs, buf_size;
@@ -496,19 +497,80 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp)
496 for (i = 0; i < algs; i++) { 497 for (i = 0; i < algs; i++) {
497 switch (dsp->type) { 498 switch (dsp->type) {
498 case WMFW_ADSP1: 499 case WMFW_ADSP1:
499 adsp_info(dsp, "%d: ID %x v%d.%d.%d\n", 500 adsp_info(dsp, "%d: ID %x v%d.%d.%d DM@%x ZM@%x\n",
500 i, be32_to_cpu(adsp1_alg[i].alg.id), 501 i, be32_to_cpu(adsp1_alg[i].alg.id),
501 (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff0000) >> 16, 502 (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff0000) >> 16,
502 (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff00) >> 8, 503 (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff00) >> 8,
503 be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff); 504 be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff,
505 be32_to_cpu(adsp1_alg[i].dm),
506 be32_to_cpu(adsp1_alg[i].zm));
507
508 if (adsp1_alg[i].dm) {
509 region = kzalloc(sizeof(*region), GFP_KERNEL);
510 if (!region)
511 return -ENOMEM;
512 region->type = WMFW_ADSP1_DM;
513 region->alg = be32_to_cpu(adsp1_alg[i].alg.id);
514 region->base = be32_to_cpu(adsp1_alg[i].dm);
515 list_add_tail(&region->list,
516 &dsp->alg_regions);
517 }
518
519 if (adsp1_alg[i].zm) {
520 region = kzalloc(sizeof(*region), GFP_KERNEL);
521 if (!region)
522 return -ENOMEM;
523 region->type = WMFW_ADSP1_ZM;
524 region->alg = be32_to_cpu(adsp1_alg[i].alg.id);
525 region->base = be32_to_cpu(adsp1_alg[i].zm);
526 list_add_tail(&region->list,
527 &dsp->alg_regions);
528 }
504 break; 529 break;
505 530
506 case WMFW_ADSP2: 531 case WMFW_ADSP2:
507 adsp_info(dsp, "%d: ID %x v%d.%d.%d\n", 532 adsp_info(dsp,
533 "%d: ID %x v%d.%d.%d XM@%x YM@%x ZM@%x\n",
508 i, be32_to_cpu(adsp2_alg[i].alg.id), 534 i, be32_to_cpu(adsp2_alg[i].alg.id),
509 (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff0000) >> 16, 535 (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff0000) >> 16,
510 (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff00) >> 8, 536 (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff00) >> 8,
511 be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff); 537 be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff,
538 be32_to_cpu(adsp2_alg[i].xm),
539 be32_to_cpu(adsp2_alg[i].ym),
540 be32_to_cpu(adsp2_alg[i].zm));
541
542 if (adsp2_alg[i].xm) {
543 region = kzalloc(sizeof(*region), GFP_KERNEL);
544 if (!region)
545 return -ENOMEM;
546 region->type = WMFW_ADSP2_XM;
547 region->alg = be32_to_cpu(adsp2_alg[i].alg.id);
548 region->base = be32_to_cpu(adsp2_alg[i].xm);
549 list_add_tail(&region->list,
550 &dsp->alg_regions);
551 }
552
553 if (adsp2_alg[i].ym) {
554 region = kzalloc(sizeof(*region), GFP_KERNEL);
555 if (!region)
556 return -ENOMEM;
557 region->type = WMFW_ADSP2_YM;
558 region->alg = be32_to_cpu(adsp2_alg[i].alg.id);
559 region->base = be32_to_cpu(adsp2_alg[i].ym);
560 list_add_tail(&region->list,
561 &dsp->alg_regions);
562 }
563
564 if (adsp2_alg[i].zm) {
565 region = kzalloc(sizeof(*region), GFP_KERNEL);
566 if (!region)
567 return -ENOMEM;
568 region->type = WMFW_ADSP2_ZM;
569 region->alg = be32_to_cpu(adsp2_alg[i].alg.id);
570 region->base = be32_to_cpu(adsp2_alg[i].zm);
571 list_add_tail(&region->list,
572 &dsp->alg_regions);
573 }
512 break; 574 break;
513 } 575 }
514 } 576 }
@@ -524,6 +586,8 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
524 struct wmfw_coeff_hdr *hdr; 586 struct wmfw_coeff_hdr *hdr;
525 struct wmfw_coeff_item *blk; 587 struct wmfw_coeff_item *blk;
526 const struct firmware *firmware; 588 const struct firmware *firmware;
589 const struct wm_adsp_region *mem;
590 struct wm_adsp_alg_region *alg_region;
527 const char *region_name; 591 const char *region_name;
528 int ret, pos, blocks, type, offset, reg; 592 int ret, pos, blocks, type, offset, reg;
529 char *file; 593 char *file;
@@ -588,6 +652,37 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
588 region_name = "register"; 652 region_name = "register";
589 reg = offset; 653 reg = offset;
590 break; 654 break;
655
656 case WMFW_ADSP1_DM:
657 case WMFW_ADSP1_ZM:
658 case WMFW_ADSP2_XM:
659 case WMFW_ADSP2_YM:
660 adsp_dbg(dsp, "%s.%d: %d bytes in %x for %x\n",
661 file, blocks, le32_to_cpu(blk->len),
662 type, le32_to_cpu(blk->id));
663
664 mem = wm_adsp_find_region(dsp, type);
665 if (!mem) {
666 adsp_err(dsp, "No base for region %x\n", type);
667 break;
668 }
669
670 reg = 0;
671 list_for_each_entry(alg_region,
672 &dsp->alg_regions, list) {
673 if (le32_to_cpu(blk->id) == alg_region->alg &&
674 type == alg_region->type) {
675 reg = alg_region->base + offset;
676 reg = wm_adsp_region_to_reg(mem,
677 reg);
678 }
679 }
680
681 if (reg == 0)
682 adsp_err(dsp, "No %x for algorithm %x\n",
683 type, le32_to_cpu(blk->id));
684 break;
685
591 default: 686 default:
592 adsp_err(dsp, "Unknown region type %x\n", type); 687 adsp_err(dsp, "Unknown region type %x\n", type);
593 break; 688 break;
@@ -711,6 +806,7 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
711 struct snd_soc_codec *codec = w->codec; 806 struct snd_soc_codec *codec = w->codec;
712 struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); 807 struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
713 struct wm_adsp *dsp = &dsps[w->shift]; 808 struct wm_adsp *dsp = &dsps[w->shift];
809 struct wm_adsp_alg_region *alg_region;
714 unsigned int val; 810 unsigned int val;
715 int ret; 811 int ret;
716 812
@@ -811,6 +907,14 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
811 "Failed to enable supply: %d\n", 907 "Failed to enable supply: %d\n",
812 ret); 908 ret);
813 } 909 }
910
911 while (!list_empty(&dsp->alg_regions)) {
912 alg_region = list_first_entry(&dsp->alg_regions,
913 struct wm_adsp_alg_region,
914 list);
915 list_del(&alg_region->list);
916 kfree(alg_region);
917 }
814 break; 918 break;
815 919
816 default: 920 default:
@@ -840,6 +944,8 @@ int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs)
840 return ret; 944 return ret;
841 } 945 }
842 946
947 INIT_LIST_HEAD(&adsp->alg_regions);
948
843 if (dvfs) { 949 if (dvfs) {
844 adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD"); 950 adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD");
845 if (IS_ERR(adsp->dvfs)) { 951 if (IS_ERR(adsp->dvfs)) {
diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h
index ffd29a4609e2..48814198e24e 100644
--- a/sound/soc/codecs/wm_adsp.h
+++ b/sound/soc/codecs/wm_adsp.h
@@ -25,6 +25,13 @@ struct wm_adsp_region {
25 unsigned int base; 25 unsigned int base;
26}; 26};
27 27
28struct wm_adsp_alg_region {
29 struct list_head list;
30 unsigned int alg;
31 int type;
32 unsigned int base;
33};
34
28struct wm_adsp { 35struct wm_adsp {
29 const char *part; 36 const char *part;
30 int num; 37 int num;
@@ -34,6 +41,8 @@ struct wm_adsp {
34 41
35 int base; 42 int base;
36 43
44 struct list_head alg_regions;
45
37 const struct wm_adsp_region *mem; 46 const struct wm_adsp_region *mem;
38 int num_mems; 47 int num_mems;
39 48