diff options
-rw-r--r-- | sound/soc/codecs/wm_adsp.c | 114 | ||||
-rw-r--r-- | sound/soc/codecs/wm_adsp.h | 9 |
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(®ion->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(®ion->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(®ion->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(®ion->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(®ion->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 | ||
28 | struct wm_adsp_alg_region { | ||
29 | struct list_head list; | ||
30 | unsigned int alg; | ||
31 | int type; | ||
32 | unsigned int base; | ||
33 | }; | ||
34 | |||
28 | struct wm_adsp { | 35 | struct 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 | ||