aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/soc/codecs/wm_adsp.c137
1 files changed, 119 insertions, 18 deletions
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index 16b308a6bfbb..1c45d67cfb4f 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -598,8 +598,31 @@ static int wm_adsp_create_control(struct wm_adsp *dsp,
598 return -EINVAL; 598 return -EINVAL;
599 } 599 }
600 600
601 snprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "DSP%d %s %x", 601 switch (dsp->fw_ver) {
602 dsp->num, region_name, alg_region->alg); 602 case 0:
603 case 1:
604 snprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "DSP%d %s %x",
605 dsp->num, region_name, alg_region->alg);
606 break;
607 default:
608 ret = snprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
609 "DSP%d%c %.12s %x", dsp->num, *region_name,
610 wm_adsp_fw_text[dsp->fw], alg_region->alg);
611
612 /* Truncate the subname from the start if it is too long */
613 if (subname) {
614 int avail = SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret - 2;
615 int skip = 0;
616
617 if (subname_len > avail)
618 skip = subname_len - avail;
619
620 snprintf(name + ret,
621 SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret, " %.*s",
622 subname_len - skip, subname + skip);
623 }
624 break;
625 }
603 626
604 list_for_each_entry(ctl, &dsp->ctl_list, 627 list_for_each_entry(ctl, &dsp->ctl_list,
605 list) { 628 list) {
@@ -681,18 +704,73 @@ struct wm_coeff_parsed_coeff {
681 int len; 704 int len;
682}; 705};
683 706
707static int wm_coeff_parse_string(int bytes, const u8 **pos, const u8 **str)
708{
709 int length;
710
711 switch (bytes) {
712 case 1:
713 length = **pos;
714 break;
715 case 2:
716 length = le16_to_cpu(*((u16 *)*pos));
717 break;
718 default:
719 return 0;
720 }
721
722 if (str)
723 *str = *pos + bytes;
724
725 *pos += ((length + bytes) + 3) & ~0x03;
726
727 return length;
728}
729
730static int wm_coeff_parse_int(int bytes, const u8 **pos)
731{
732 int val = 0;
733
734 switch (bytes) {
735 case 2:
736 val = le16_to_cpu(*((u16 *)*pos));
737 break;
738 case 4:
739 val = le32_to_cpu(*((u32 *)*pos));
740 break;
741 default:
742 break;
743 }
744
745 *pos += bytes;
746
747 return val;
748}
749
684static inline void wm_coeff_parse_alg(struct wm_adsp *dsp, const u8 **data, 750static inline void wm_coeff_parse_alg(struct wm_adsp *dsp, const u8 **data,
685 struct wm_coeff_parsed_alg *blk) 751 struct wm_coeff_parsed_alg *blk)
686{ 752{
687 const struct wmfw_adsp_alg_data *raw; 753 const struct wmfw_adsp_alg_data *raw;
688 754
689 raw = (const struct wmfw_adsp_alg_data *)*data; 755 switch (dsp->fw_ver) {
690 *data = raw->data; 756 case 0:
757 case 1:
758 raw = (const struct wmfw_adsp_alg_data *)*data;
759 *data = raw->data;
691 760
692 blk->id = le32_to_cpu(raw->id); 761 blk->id = le32_to_cpu(raw->id);
693 blk->name = raw->name; 762 blk->name = raw->name;
694 blk->name_len = strlen(raw->name); 763 blk->name_len = strlen(raw->name);
695 blk->ncoeff = le32_to_cpu(raw->ncoeff); 764 blk->ncoeff = le32_to_cpu(raw->ncoeff);
765 break;
766 default:
767 blk->id = wm_coeff_parse_int(sizeof(raw->id), data);
768 blk->name_len = wm_coeff_parse_string(sizeof(u8), data,
769 &blk->name);
770 wm_coeff_parse_string(sizeof(u16), data, NULL);
771 blk->ncoeff = wm_coeff_parse_int(sizeof(raw->ncoeff), data);
772 break;
773 }
696 774
697 adsp_dbg(dsp, "Algorithm ID: %#x\n", blk->id); 775 adsp_dbg(dsp, "Algorithm ID: %#x\n", blk->id);
698 adsp_dbg(dsp, "Algorithm name: %.*s\n", blk->name_len, blk->name); 776 adsp_dbg(dsp, "Algorithm name: %.*s\n", blk->name_len, blk->name);
@@ -703,17 +781,39 @@ static inline void wm_coeff_parse_coeff(struct wm_adsp *dsp, const u8 **data,
703 struct wm_coeff_parsed_coeff *blk) 781 struct wm_coeff_parsed_coeff *blk)
704{ 782{
705 const struct wmfw_adsp_coeff_data *raw; 783 const struct wmfw_adsp_coeff_data *raw;
784 const u8 *tmp;
785 int length;
706 786
707 raw = (const struct wmfw_adsp_coeff_data *)*data; 787 switch (dsp->fw_ver) {
708 *data = *data + sizeof(raw->hdr) + le32_to_cpu(raw->hdr.size); 788 case 0:
709 789 case 1:
710 blk->offset = le16_to_cpu(raw->hdr.offset); 790 raw = (const struct wmfw_adsp_coeff_data *)*data;
711 blk->mem_type = le16_to_cpu(raw->hdr.type); 791 *data = *data + sizeof(raw->hdr) + le32_to_cpu(raw->hdr.size);
712 blk->name = raw->name; 792
713 blk->name_len = strlen(raw->name); 793 blk->offset = le16_to_cpu(raw->hdr.offset);
714 blk->ctl_type = le16_to_cpu(raw->ctl_type); 794 blk->mem_type = le16_to_cpu(raw->hdr.type);
715 blk->flags = le16_to_cpu(raw->flags); 795 blk->name = raw->name;
716 blk->len = le32_to_cpu(raw->len); 796 blk->name_len = strlen(raw->name);
797 blk->ctl_type = le16_to_cpu(raw->ctl_type);
798 blk->flags = le16_to_cpu(raw->flags);
799 blk->len = le32_to_cpu(raw->len);
800 break;
801 default:
802 tmp = *data;
803 blk->offset = wm_coeff_parse_int(sizeof(raw->hdr.offset), &tmp);
804 blk->mem_type = wm_coeff_parse_int(sizeof(raw->hdr.type), &tmp);
805 length = wm_coeff_parse_int(sizeof(raw->hdr.size), &tmp);
806 blk->name_len = wm_coeff_parse_string(sizeof(u8), &tmp,
807 &blk->name);
808 wm_coeff_parse_string(sizeof(u8), &tmp, NULL);
809 wm_coeff_parse_string(sizeof(u16), &tmp, NULL);
810 blk->ctl_type = wm_coeff_parse_int(sizeof(raw->ctl_type), &tmp);
811 blk->flags = wm_coeff_parse_int(sizeof(raw->flags), &tmp);
812 blk->len = wm_coeff_parse_int(sizeof(raw->len), &tmp);
813
814 *data = *data + sizeof(raw->hdr) + length;
815 break;
816 }
717 817
718 adsp_dbg(dsp, "\tCoefficient type: %#x\n", blk->mem_type); 818 adsp_dbg(dsp, "\tCoefficient type: %#x\n", blk->mem_type);
719 adsp_dbg(dsp, "\tCoefficient offset: %#x\n", blk->offset); 819 adsp_dbg(dsp, "\tCoefficient offset: %#x\n", blk->offset);
@@ -812,6 +912,7 @@ static int wm_adsp_load(struct wm_adsp *dsp)
812 switch (header->ver) { 912 switch (header->ver) {
813 case 0: 913 case 0:
814 case 1: 914 case 1:
915 case 2:
815 break; 916 break;
816 default: 917 default:
817 adsp_err(dsp, "%s: unknown file format %d\n", 918 adsp_err(dsp, "%s: unknown file format %d\n",