Merge remote-tracking branch 'asoc/fix/adsp' into asoc-adsp
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Mon, 21 Jan 2013 08:46:16 +0000 (17:46 +0900)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Mon, 21 Jan 2013 08:46:16 +0000 (17:46 +0900)
sound/soc/codecs/wm_adsp.c
sound/soc/codecs/wm_adsp.h
sound/soc/codecs/wmfw.h

index 4196f2d54967253d154efd36c0867f658b7d0b2f..76ca176eac0712a973b03a8b8d5e152fdc475628 100644 (file)
 #define ADSP1_START_SHIFT                      0  /* DSP1_START */
 #define ADSP1_START_WIDTH                      1  /* DSP1_START */
 
+/*
+ * ADSP1 Control 31
+ */
+#define ADSP1_CLK_SEL_MASK                0x0007  /* CLK_SEL_ENA */
+#define ADSP1_CLK_SEL_SHIFT                    0  /* CLK_SEL_ENA */
+#define ADSP1_CLK_SEL_WIDTH                    3  /* CLK_SEL_ENA */
+
 #define ADSP2_CONTROL  0
 #define ADSP2_CLOCKING 1
 #define ADSP2_STATUS1  4
 #define ADSP2_RAM_RDY_SHIFT                    0
 #define ADSP2_RAM_RDY_WIDTH                    1
 
+#define WM_ADSP_NUM_FW 3
+
+static const char *wm_adsp_fw_text[WM_ADSP_NUM_FW] = {
+       "MBC/VSS", "Tx", "Rx ANC"
+};
+
+static struct {
+       const char *file;
+} wm_adsp_fw[WM_ADSP_NUM_FW] = {
+       { .file = "mbc-vss" },
+       { .file = "tx" },
+       { .file = "rx-anc" },
+};
+
+static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol,
+                         struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+       struct wm_adsp *adsp = snd_soc_codec_get_drvdata(codec);
+
+       ucontrol->value.integer.value[0] = adsp[e->shift_l].fw;
+
+       return 0;
+}
+
+static int wm_adsp_fw_put(struct snd_kcontrol *kcontrol,
+                         struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+       struct wm_adsp *adsp = snd_soc_codec_get_drvdata(codec);
+
+       if (ucontrol->value.integer.value[0] == adsp[e->shift_l].fw)
+               return 0;
+
+       if (ucontrol->value.integer.value[0] >= WM_ADSP_NUM_FW)
+               return -EINVAL;
+
+       if (adsp[e->shift_l].running)
+               return -EBUSY;
+
+       adsp->fw = ucontrol->value.integer.value[0];
+
+       return 0;
+}
+
+static const struct soc_enum wm_adsp_fw_enum[] = {
+       SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
+       SOC_ENUM_SINGLE(0, 1, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
+       SOC_ENUM_SINGLE(0, 2, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
+       SOC_ENUM_SINGLE(0, 3, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
+};
+
+const struct snd_kcontrol_new wm_adsp_fw_controls[] = {
+       SOC_ENUM_EXT("DSP1 Firmware", wm_adsp_fw_enum[0],
+                    wm_adsp_fw_get, wm_adsp_fw_put),
+       SOC_ENUM_EXT("DSP2 Firmware", wm_adsp_fw_enum[1],
+                    wm_adsp_fw_get, wm_adsp_fw_put),
+       SOC_ENUM_EXT("DSP3 Firmware", wm_adsp_fw_enum[2],
+                    wm_adsp_fw_get, wm_adsp_fw_put),
+       SOC_ENUM_EXT("DSP4 Firmware", wm_adsp_fw_enum[3],
+                    wm_adsp_fw_get, wm_adsp_fw_put),
+};
+EXPORT_SYMBOL_GPL(wm_adsp_fw_controls);
 
 static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp,
                                                        int type)
@@ -156,6 +228,26 @@ static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp,
        return NULL;
 }
 
+static unsigned int wm_adsp_region_to_reg(struct wm_adsp_region const *region,
+                                         unsigned int offset)
+{
+       switch (region->type) {
+       case WMFW_ADSP1_PM:
+               return region->base + (offset * 3);
+       case WMFW_ADSP1_DM:
+               return region->base + (offset * 2);
+       case WMFW_ADSP2_XM:
+               return region->base + (offset * 2);
+       case WMFW_ADSP2_YM:
+               return region->base + (offset * 2);
+       case WMFW_ADSP1_ZM:
+               return region->base + (offset * 2);
+       default:
+               WARN_ON(NULL != "Unknown memory region type");
+               return offset;
+       }
+}
+
 static int wm_adsp_load(struct wm_adsp *dsp)
 {
        const struct firmware *firmware;
@@ -178,7 +270,8 @@ static int wm_adsp_load(struct wm_adsp *dsp)
        if (file == NULL)
                return -ENOMEM;
 
-       snprintf(file, PAGE_SIZE, "%s-dsp%d.wmfw", dsp->part, dsp->num);
+       snprintf(file, PAGE_SIZE, "%s-dsp%d-%s.wmfw", dsp->part, dsp->num,
+                wm_adsp_fw[dsp->fw].file);
        file[PAGE_SIZE - 1] = '\0';
 
        ret = request_firmware(&firmware, file, dsp->dev);
@@ -283,27 +376,27 @@ static int wm_adsp_load(struct wm_adsp *dsp)
                case WMFW_ADSP1_PM:
                        BUG_ON(!mem);
                        region_name = "PM";
-                       reg = mem->base + (offset * 3);
+                       reg = wm_adsp_region_to_reg(mem, offset);
                        break;
                case WMFW_ADSP1_DM:
                        BUG_ON(!mem);
                        region_name = "DM";
-                       reg = mem->base + (offset * 2);
+                       reg = wm_adsp_region_to_reg(mem, offset);
                        break;
                case WMFW_ADSP2_XM:
                        BUG_ON(!mem);
                        region_name = "XM";
-                       reg = mem->base + (offset * 2);
+                       reg = wm_adsp_region_to_reg(mem, offset);
                        break;
                case WMFW_ADSP2_YM:
                        BUG_ON(!mem);
                        region_name = "YM";
-                       reg = mem->base + (offset * 2);
+                       reg = wm_adsp_region_to_reg(mem, offset);
                        break;
                case WMFW_ADSP1_ZM:
                        BUG_ON(!mem);
                        region_name = "ZM";
-                       reg = mem->base + (offset * 2);
+                       reg = wm_adsp_region_to_reg(mem, offset);
                        break;
                default:
                        adsp_warn(dsp,
@@ -361,12 +454,224 @@ out:
        return ret;
 }
 
+static int wm_adsp_setup_algs(struct wm_adsp *dsp)
+{
+       struct regmap *regmap = dsp->regmap;
+       struct wmfw_adsp1_id_hdr adsp1_id;
+       struct wmfw_adsp2_id_hdr adsp2_id;
+       struct wmfw_adsp1_alg_hdr *adsp1_alg;
+       struct wmfw_adsp2_alg_hdr *adsp2_alg;
+       void *alg, *buf;
+       struct wm_adsp_alg_region *region;
+       const struct wm_adsp_region *mem;
+       unsigned int pos, term;
+       size_t algs, buf_size;
+       __be32 val;
+       int i, ret;
+
+       switch (dsp->type) {
+       case WMFW_ADSP1:
+               mem = wm_adsp_find_region(dsp, WMFW_ADSP1_DM);
+               break;
+       case WMFW_ADSP2:
+               mem = wm_adsp_find_region(dsp, WMFW_ADSP2_XM);
+               break;
+       default:
+               mem = NULL;
+               break;
+       }
+
+       if (mem == NULL) {
+               BUG_ON(mem != NULL);
+               return -EINVAL;
+       }
+
+       switch (dsp->type) {
+       case WMFW_ADSP1:
+               ret = regmap_raw_read(regmap, mem->base, &adsp1_id,
+                                     sizeof(adsp1_id));
+               if (ret != 0) {
+                       adsp_err(dsp, "Failed to read algorithm info: %d\n",
+                                ret);
+                       return ret;
+               }
+
+               buf = &adsp1_id;
+               buf_size = sizeof(adsp1_id);
+
+               algs = be32_to_cpu(adsp1_id.algs);
+               adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n",
+                         be32_to_cpu(adsp1_id.fw.id),
+                         (be32_to_cpu(adsp1_id.fw.ver) & 0xff0000) >> 16,
+                         (be32_to_cpu(adsp1_id.fw.ver) & 0xff00) >> 8,
+                         be32_to_cpu(adsp1_id.fw.ver) & 0xff,
+                         algs);
+
+               pos = sizeof(adsp1_id) / 2;
+               term = pos + ((sizeof(*adsp1_alg) * algs) / 2);
+               break;
+
+       case WMFW_ADSP2:
+               ret = regmap_raw_read(regmap, mem->base, &adsp2_id,
+                                     sizeof(adsp2_id));
+               if (ret != 0) {
+                       adsp_err(dsp, "Failed to read algorithm info: %d\n",
+                                ret);
+                       return ret;
+               }
+
+               buf = &adsp2_id;
+               buf_size = sizeof(adsp2_id);
+
+               algs = be32_to_cpu(adsp2_id.algs);
+               adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n",
+                         be32_to_cpu(adsp2_id.fw.id),
+                         (be32_to_cpu(adsp2_id.fw.ver) & 0xff0000) >> 16,
+                         (be32_to_cpu(adsp2_id.fw.ver) & 0xff00) >> 8,
+                         be32_to_cpu(adsp2_id.fw.ver) & 0xff,
+                         algs);
+
+               pos = sizeof(adsp2_id) / 2;
+               term = pos + ((sizeof(*adsp2_alg) * algs) / 2);
+               break;
+
+       default:
+               BUG_ON(NULL == "Unknown DSP type");
+               return -EINVAL;
+       }
+
+       if (algs == 0) {
+               adsp_err(dsp, "No algorithms\n");
+               return -EINVAL;
+       }
+
+       if (algs > 1024) {
+               adsp_err(dsp, "Algorithm count %zx excessive\n", algs);
+               print_hex_dump_bytes(dev_name(dsp->dev), DUMP_PREFIX_OFFSET,
+                                    buf, buf_size);
+               return -EINVAL;
+       }
+
+       /* Read the terminator first to validate the length */
+       ret = regmap_raw_read(regmap, mem->base + term, &val, sizeof(val));
+       if (ret != 0) {
+               adsp_err(dsp, "Failed to read algorithm list end: %d\n",
+                       ret);
+               return ret;
+       }
+
+       if (be32_to_cpu(val) != 0xbedead)
+               adsp_warn(dsp, "Algorithm list end %x 0x%x != 0xbeadead\n",
+                         term, be32_to_cpu(val));
+
+       alg = kzalloc((term - pos) * 2, GFP_KERNEL | GFP_DMA);
+       if (!alg)
+               return -ENOMEM;
+
+       ret = regmap_raw_read(regmap, mem->base + pos, alg, (term - pos) * 2);
+       if (ret != 0) {
+               adsp_err(dsp, "Failed to read algorithm list: %d\n",
+                       ret);
+               goto out;
+       }
+
+       adsp1_alg = alg;
+       adsp2_alg = alg;
+
+       for (i = 0; i < algs; i++) {
+               switch (dsp->type) {
+               case WMFW_ADSP1:
+                       adsp_info(dsp, "%d: ID %x v%d.%d.%d DM@%x ZM@%x\n",
+                                 i, be32_to_cpu(adsp1_alg[i].alg.id),
+                                 (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff0000) >> 16,
+                                 (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff00) >> 8,
+                                 be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff,
+                                 be32_to_cpu(adsp1_alg[i].dm),
+                                 be32_to_cpu(adsp1_alg[i].zm));
+
+                       if (adsp1_alg[i].dm) {
+                               region = kzalloc(sizeof(*region), GFP_KERNEL);
+                               if (!region)
+                                       return -ENOMEM;
+                               region->type = WMFW_ADSP1_DM;
+                               region->alg = be32_to_cpu(adsp1_alg[i].alg.id);
+                               region->base = be32_to_cpu(adsp1_alg[i].dm);
+                               list_add_tail(&region->list,
+                                             &dsp->alg_regions);
+                       }
+
+                       if (adsp1_alg[i].zm) {
+                               region = kzalloc(sizeof(*region), GFP_KERNEL);
+                               if (!region)
+                                       return -ENOMEM;
+                               region->type = WMFW_ADSP1_ZM;
+                               region->alg = be32_to_cpu(adsp1_alg[i].alg.id);
+                               region->base = be32_to_cpu(adsp1_alg[i].zm);
+                               list_add_tail(&region->list,
+                                             &dsp->alg_regions);
+                       }
+                       break;
+
+               case WMFW_ADSP2:
+                       adsp_info(dsp,
+                                 "%d: ID %x v%d.%d.%d XM@%x YM@%x ZM@%x\n",
+                                 i, be32_to_cpu(adsp2_alg[i].alg.id),
+                                 (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff0000) >> 16,
+                                 (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff00) >> 8,
+                                 be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff,
+                                 be32_to_cpu(adsp2_alg[i].xm),
+                                 be32_to_cpu(adsp2_alg[i].ym),
+                                 be32_to_cpu(adsp2_alg[i].zm));
+
+                       if (adsp2_alg[i].xm) {
+                               region = kzalloc(sizeof(*region), GFP_KERNEL);
+                               if (!region)
+                                       return -ENOMEM;
+                               region->type = WMFW_ADSP2_XM;
+                               region->alg = be32_to_cpu(adsp2_alg[i].alg.id);
+                               region->base = be32_to_cpu(adsp2_alg[i].xm);
+                               list_add_tail(&region->list,
+                                             &dsp->alg_regions);
+                       }
+
+                       if (adsp2_alg[i].ym) {
+                               region = kzalloc(sizeof(*region), GFP_KERNEL);
+                               if (!region)
+                                       return -ENOMEM;
+                               region->type = WMFW_ADSP2_YM;
+                               region->alg = be32_to_cpu(adsp2_alg[i].alg.id);
+                               region->base = be32_to_cpu(adsp2_alg[i].ym);
+                               list_add_tail(&region->list,
+                                             &dsp->alg_regions);
+                       }
+
+                       if (adsp2_alg[i].zm) {
+                               region = kzalloc(sizeof(*region), GFP_KERNEL);
+                               if (!region)
+                                       return -ENOMEM;
+                               region->type = WMFW_ADSP2_ZM;
+                               region->alg = be32_to_cpu(adsp2_alg[i].alg.id);
+                               region->base = be32_to_cpu(adsp2_alg[i].zm);
+                               list_add_tail(&region->list,
+                                             &dsp->alg_regions);
+                       }
+                       break;
+               }
+       }
+
+out:
+       kfree(alg);
+       return ret;
+}
+
 static int wm_adsp_load_coeff(struct wm_adsp *dsp)
 {
        struct regmap *regmap = dsp->regmap;
        struct wmfw_coeff_hdr *hdr;
        struct wmfw_coeff_item *blk;
        const struct firmware *firmware;
+       const struct wm_adsp_region *mem;
+       struct wm_adsp_alg_region *alg_region;
        const char *region_name;
        int ret, pos, blocks, type, offset, reg;
        char *file;
@@ -376,7 +681,8 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
        if (file == NULL)
                return -ENOMEM;
 
-       snprintf(file, PAGE_SIZE, "%s-dsp%d.bin", dsp->part, dsp->num);
+       snprintf(file, PAGE_SIZE, "%s-dsp%d-%s.bin", dsp->part, dsp->num,
+                wm_adsp_fw[dsp->fw].file);
        file[PAGE_SIZE - 1] = '\0';
 
        ret = request_firmware(&firmware, file, dsp->dev);
@@ -399,6 +705,16 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
                return -EINVAL;
        }
 
+       switch (be32_to_cpu(hdr->rev) & 0xff) {
+       case 1:
+               break;
+       default:
+               adsp_err(dsp, "%s: Unsupported coefficient file format %d\n",
+                        file, be32_to_cpu(hdr->rev) & 0xff);
+               ret = -EINVAL;
+               goto out_fw;
+       }
+
        adsp_dbg(dsp, "%s: v%d.%d.%d\n", file,
                (le32_to_cpu(hdr->ver) >> 16) & 0xff,
                (le32_to_cpu(hdr->ver) >>  8) & 0xff,
@@ -411,8 +727,8 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
               pos - firmware->size > sizeof(*blk)) {
                blk = (void*)(&firmware->data[pos]);
 
-               type = be32_to_cpu(blk->type) & 0xff;
-               offset = le32_to_cpu(blk->offset) & 0xffffff;
+               type = le16_to_cpu(blk->type);
+               offset = le16_to_cpu(blk->offset);
 
                adsp_dbg(dsp, "%s.%d: %x v%d.%d.%d\n",
                         file, blocks, le32_to_cpu(blk->id),
@@ -425,15 +741,47 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
                reg = 0;
                region_name = "Unknown";
                switch (type) {
-               case WMFW_NAME_TEXT:
-               case WMFW_INFO_TEXT:
+               case (WMFW_NAME_TEXT << 8):
+               case (WMFW_INFO_TEXT << 8):
                        break;
-               case WMFW_ABSOLUTE:
+               case (WMFW_ABSOLUTE << 8):
                        region_name = "register";
                        reg = offset;
                        break;
+
+               case WMFW_ADSP1_DM:
+               case WMFW_ADSP1_ZM:
+               case WMFW_ADSP2_XM:
+               case WMFW_ADSP2_YM:
+                       adsp_dbg(dsp, "%s.%d: %d bytes in %x for %x\n",
+                                file, blocks, le32_to_cpu(blk->len),
+                                type, le32_to_cpu(blk->id));
+
+                       mem = wm_adsp_find_region(dsp, type);
+                       if (!mem) {
+                               adsp_err(dsp, "No base for region %x\n", type);
+                               break;
+                       }
+
+                       reg = 0;
+                       list_for_each_entry(alg_region,
+                                           &dsp->alg_regions, list) {
+                               if (le32_to_cpu(blk->id) == alg_region->alg &&
+                                   type == alg_region->type) {
+                                       reg = alg_region->base + offset;
+                                       reg = wm_adsp_region_to_reg(mem,
+                                                                   reg);
+                               }
+                       }
+
+                       if (reg == 0)
+                               adsp_err(dsp, "No %x for algorithm %x\n",
+                                        type, le32_to_cpu(blk->id));
+                       break;
+
                default:
-                       adsp_err(dsp, "Unknown region type %x\n", type);
+                       adsp_err(dsp, "%s.%d: Unknown region type %x at %d\n",
+                                file, blocks, type, pos);
                        break;
                }
 
@@ -471,6 +819,14 @@ out:
        return 0;
 }
 
+int wm_adsp1_init(struct wm_adsp *adsp)
+{
+       INIT_LIST_HEAD(&adsp->alg_regions);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(wm_adsp1_init);
+
 int wm_adsp1_event(struct snd_soc_dapm_widget *w,
                   struct snd_kcontrol *kcontrol,
                   int event)
@@ -479,16 +835,46 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
        struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
        struct wm_adsp *dsp = &dsps[w->shift];
        int ret;
+       int val;
 
        switch (event) {
        case SND_SOC_DAPM_POST_PMU:
                regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
                                   ADSP1_SYS_ENA, ADSP1_SYS_ENA);
 
+               /*
+                * For simplicity set the DSP clock rate to be the
+                * SYSCLK rate rather than making it configurable.
+                */
+               if(dsp->sysclk_reg) {
+                       ret = regmap_read(dsp->regmap, dsp->sysclk_reg, &val);
+                       if (ret != 0) {
+                               adsp_err(dsp, "Failed to read SYSCLK state: %d\n",
+                               ret);
+                               return ret;
+                       }
+
+                       val = (val & dsp->sysclk_mask)
+                               >> dsp->sysclk_shift;
+
+                       ret = regmap_update_bits(dsp->regmap,
+                                                dsp->base + ADSP1_CONTROL_31,
+                                                ADSP1_CLK_SEL_MASK, val);
+                       if (ret != 0) {
+                               adsp_err(dsp, "Failed to set clock rate: %d\n",
+                                        ret);
+                               return ret;
+                       }
+               }
+
                ret = wm_adsp_load(dsp);
                if (ret != 0)
                        goto err;
 
+               ret = wm_adsp_setup_algs(dsp);
+               if (ret != 0)
+                       goto err;
+
                ret = wm_adsp_load_coeff(dsp);
                if (ret != 0)
                        goto err;
@@ -560,6 +946,7 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
        struct snd_soc_codec *codec = w->codec;
        struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
        struct wm_adsp *dsp = &dsps[w->shift];
+       struct wm_adsp_alg_region *alg_region;
        unsigned int val;
        int ret;
 
@@ -625,6 +1012,10 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
                if (ret != 0)
                        goto err;
 
+               ret = wm_adsp_setup_algs(dsp);
+               if (ret != 0)
+                       goto err;
+
                ret = wm_adsp_load_coeff(dsp);
                if (ret != 0)
                        goto err;
@@ -635,9 +1026,13 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
                                         ADSP2_CORE_ENA | ADSP2_START);
                if (ret != 0)
                        goto err;
+
+               dsp->running = true;
                break;
 
        case SND_SOC_DAPM_PRE_PMD:
+               dsp->running = false;
+
                regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
                                   ADSP2_SYS_ENA | ADSP2_CORE_ENA |
                                   ADSP2_START, 0);
@@ -656,6 +1051,14 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
                                        "Failed to enable supply: %d\n",
                                        ret);
                }
+
+               while (!list_empty(&dsp->alg_regions)) {
+                       alg_region = list_first_entry(&dsp->alg_regions,
+                                                     struct wm_adsp_alg_region,
+                                                     list);
+                       list_del(&alg_region->list);
+                       kfree(alg_region);
+               }
                break;
 
        default:
@@ -685,6 +1088,8 @@ int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs)
                return ret;
        }
 
+       INIT_LIST_HEAD(&adsp->alg_regions);
+
        if (dvfs) {
                adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD");
                if (IS_ERR(adsp->dvfs)) {
index ffd29a4609e2a50b1214fc5389a73906973d9538..cb8871a3ec0015854c6d13bebb1055661b7cf4be 100644 (file)
@@ -25,6 +25,13 @@ struct wm_adsp_region {
        unsigned int base;
 };
 
+struct wm_adsp_alg_region {
+       struct list_head list;
+       unsigned int alg;
+       int type;
+       unsigned int base;
+};
+
 struct wm_adsp {
        const char *part;
        int num;
@@ -33,10 +40,18 @@ struct wm_adsp {
        struct regmap *regmap;
 
        int base;
+       int sysclk_reg;
+       int sysclk_mask;
+       int sysclk_shift;
+
+       struct list_head alg_regions;
 
        const struct wm_adsp_region *mem;
        int num_mems;
 
+       int fw;
+       bool running;
+
        struct regulator *dvfs;
 };
 
@@ -50,6 +65,9 @@ struct wm_adsp {
        .shift = num, .event = wm_adsp2_event, \
        .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD }
 
+extern const struct snd_kcontrol_new wm_adsp_fw_controls[];
+
+int wm_adsp1_init(struct wm_adsp *adsp);
 int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs);
 int wm_adsp1_event(struct snd_soc_dapm_widget *w,
                   struct snd_kcontrol *kcontrol, int event);
index 5632ded67fdd1bee57cb66ebbbff3c2de3289991..ef163360a7459ebd7a8a70af00118cbcdb95717e 100644 (file)
@@ -93,15 +93,20 @@ struct wmfw_adsp2_alg_hdr {
 struct wmfw_coeff_hdr {
        u8 magic[4];
        __le32 len;
-       __le32 ver;
+       union {
+               __be32 rev;
+               __le32 ver;
+       };
+       union {
+               __be32 core;
+               __le32 core_ver;
+       };
        u8 data[];
 } __packed;
 
 struct wmfw_coeff_item {
-       union {
-               __be32 type;
-               __le32 offset;
-       };
+       __le16 offset;
+       __le16 type;
        __le32 id;
        __le32 ver;
        __le32 sr;
This page took 0.034017 seconds and 5 git commands to generate.