aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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