]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge remote-tracking branch 'asoc/topic/adsp' into asoc-next
authorMark Brown <broonie@linaro.org>
Thu, 22 Aug 2013 13:28:25 +0000 (14:28 +0100)
committerMark Brown <broonie@linaro.org>
Thu, 22 Aug 2013 13:28:25 +0000 (14:28 +0100)
include/sound/soc.h
sound/soc/codecs/wm_adsp.c
sound/soc/codecs/wm_adsp.h
sound/soc/soc-core.c

index c0ac3bc7b7f41919e5dbff8496f8ca394958fa18..95d332851c728d4a4f362ef80bf8d6e3e5da730a 100644 (file)
@@ -477,6 +477,8 @@ int snd_soc_set_ac97_ops_of_reset(struct snd_ac97_bus_ops *ops,
 struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
                                  void *data, const char *long_name,
                                  const char *prefix);
+struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card,
+                                              const char *name);
 int snd_soc_add_codec_controls(struct snd_soc_codec *codec,
        const struct snd_kcontrol_new *controls, int num_controls);
 int snd_soc_add_platform_controls(struct snd_soc_platform *platform,
index 05252ac936a369cb210a9043105d9d95cb614679..b38f3506418ff0d43dc927fe45424e3d9d998d75 100644 (file)
@@ -225,15 +225,8 @@ struct wm_coeff_ctl_ops {
                     struct snd_ctl_elem_info *uinfo);
 };
 
-struct wm_coeff {
-       struct device *dev;
-       struct list_head ctl_list;
-       struct regmap *regmap;
-};
-
 struct wm_coeff_ctl {
        const char *name;
-       struct snd_card *card;
        struct wm_adsp_alg_region region;
        struct wm_coeff_ctl_ops ops;
        struct wm_adsp *adsp;
@@ -378,7 +371,6 @@ static int wm_coeff_info(struct snd_kcontrol *kcontrol,
 static int wm_coeff_write_control(struct snd_kcontrol *kcontrol,
                                  const void *buf, size_t len)
 {
-       struct wm_coeff *wm_coeff= snd_kcontrol_chip(kcontrol);
        struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value;
        struct wm_adsp_alg_region *region = &ctl->region;
        const struct wm_adsp_region *mem;
@@ -401,7 +393,7 @@ static int wm_coeff_write_control(struct snd_kcontrol *kcontrol,
        if (!scratch)
                return -ENOMEM;
 
-       ret = regmap_raw_write(wm_coeff->regmap, reg, scratch,
+       ret = regmap_raw_write(adsp->regmap, reg, scratch,
                               ctl->len);
        if (ret) {
                adsp_err(adsp, "Failed to write %zu bytes to %x\n",
@@ -434,7 +426,6 @@ static int wm_coeff_put(struct snd_kcontrol *kcontrol,
 static int wm_coeff_read_control(struct snd_kcontrol *kcontrol,
                                 void *buf, size_t len)
 {
-       struct wm_coeff *wm_coeff= snd_kcontrol_chip(kcontrol);
        struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value;
        struct wm_adsp_alg_region *region = &ctl->region;
        const struct wm_adsp_region *mem;
@@ -457,7 +448,7 @@ static int wm_coeff_read_control(struct snd_kcontrol *kcontrol,
        if (!scratch)
                return -ENOMEM;
 
-       ret = regmap_raw_read(wm_coeff->regmap, reg, scratch, ctl->len);
+       ret = regmap_raw_read(adsp->regmap, reg, scratch, ctl->len);
        if (ret) {
                adsp_err(adsp, "Failed to read %zu bytes from %x\n",
                         ctl->len, reg);
@@ -481,37 +472,18 @@ static int wm_coeff_get(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static int wm_coeff_add_kcontrol(struct wm_coeff *wm_coeff,
-                                struct wm_coeff_ctl *ctl,
-                                const struct snd_kcontrol_new *kctl)
-{
-       int ret;
-       struct snd_kcontrol *kcontrol;
-
-       kcontrol = snd_ctl_new1(kctl, wm_coeff);
-       ret = snd_ctl_add(ctl->card, kcontrol);
-       if (ret < 0) {
-               dev_err(wm_coeff->dev, "Failed to add %s: %d\n",
-                       kctl->name, ret);
-               return ret;
-       }
-       ctl->kcontrol = kcontrol;
-       return 0;
-}
-
 struct wmfw_ctl_work {
-       struct wm_coeff *wm_coeff;
+       struct wm_adsp *adsp;
        struct wm_coeff_ctl *ctl;
        struct work_struct work;
 };
 
-static int wmfw_add_ctl(struct wm_coeff *wm_coeff,
-                       struct wm_coeff_ctl *ctl)
+static int wmfw_add_ctl(struct wm_adsp *adsp, struct wm_coeff_ctl *ctl)
 {
        struct snd_kcontrol_new *kcontrol;
        int ret;
 
-       if (!wm_coeff || !ctl || !ctl->name || !ctl->card)
+       if (!ctl || !ctl->name)
                return -EINVAL;
 
        kcontrol = kzalloc(sizeof(*kcontrol), GFP_KERNEL);
@@ -525,14 +497,17 @@ static int wmfw_add_ctl(struct wm_coeff *wm_coeff,
        kcontrol->put = wm_coeff_put;
        kcontrol->private_value = (unsigned long)ctl;
 
-       ret = wm_coeff_add_kcontrol(wm_coeff,
-                                   ctl, kcontrol);
+       ret = snd_soc_add_card_controls(adsp->card,
+                                       kcontrol, 1);
        if (ret < 0)
                goto err_kcontrol;
 
        kfree(kcontrol);
 
-       list_add(&ctl->list, &wm_coeff->ctl_list);
+       ctl->kcontrol = snd_soc_card_get_kcontrol(adsp->card,
+                                                 ctl->name);
+
+       list_add(&ctl->list, &adsp->ctl_list);
        return 0;
 
 err_kcontrol:
@@ -753,13 +728,12 @@ out:
        return ret;
 }
 
-static int wm_coeff_init_control_caches(struct wm_coeff *wm_coeff)
+static int wm_coeff_init_control_caches(struct wm_adsp *adsp)
 {
        struct wm_coeff_ctl *ctl;
        int ret;
 
-       list_for_each_entry(ctl, &wm_coeff->ctl_list,
-                           list) {
+       list_for_each_entry(ctl, &adsp->ctl_list, list) {
                if (!ctl->enabled || ctl->set)
                        continue;
                ret = wm_coeff_read_control(ctl->kcontrol,
@@ -772,13 +746,12 @@ static int wm_coeff_init_control_caches(struct wm_coeff *wm_coeff)
        return 0;
 }
 
-static int wm_coeff_sync_controls(struct wm_coeff *wm_coeff)
+static int wm_coeff_sync_controls(struct wm_adsp *adsp)
 {
        struct wm_coeff_ctl *ctl;
        int ret;
 
-       list_for_each_entry(ctl, &wm_coeff->ctl_list,
-                           list) {
+       list_for_each_entry(ctl, &adsp->ctl_list, list) {
                if (!ctl->enabled)
                        continue;
                if (ctl->set) {
@@ -799,15 +772,14 @@ static void wm_adsp_ctl_work(struct work_struct *work)
                                                      struct wmfw_ctl_work,
                                                      work);
 
-       wmfw_add_ctl(ctl_work->wm_coeff, ctl_work->ctl);
+       wmfw_add_ctl(ctl_work->adsp, ctl_work->ctl);
        kfree(ctl_work);
 }
 
-static int wm_adsp_create_control(struct snd_soc_codec *codec,
+static int wm_adsp_create_control(struct wm_adsp *dsp,
                                  const struct wm_adsp_alg_region *region)
 
 {
-       struct wm_adsp *dsp = snd_soc_codec_get_drvdata(codec);
        struct wm_coeff_ctl *ctl;
        struct wmfw_ctl_work *ctl_work;
        char *name;
@@ -842,7 +814,7 @@ static int wm_adsp_create_control(struct snd_soc_codec *codec,
        snprintf(name, PAGE_SIZE, "DSP%d %s %x",
                 dsp->num, region_name, region->alg);
 
-       list_for_each_entry(ctl, &dsp->wm_coeff->ctl_list,
+       list_for_each_entry(ctl, &dsp->ctl_list,
                            list) {
                if (!strcmp(ctl->name, name)) {
                        if (!ctl->enabled)
@@ -866,7 +838,6 @@ static int wm_adsp_create_control(struct snd_soc_codec *codec,
        ctl->set = 0;
        ctl->ops.xget = wm_coeff_get;
        ctl->ops.xput = wm_coeff_put;
-       ctl->card = codec->card->snd_card;
        ctl->adsp = dsp;
 
        ctl->len = region->len;
@@ -882,7 +853,7 @@ static int wm_adsp_create_control(struct snd_soc_codec *codec,
                goto err_ctl_cache;
        }
 
-       ctl_work->wm_coeff = dsp->wm_coeff;
+       ctl_work->adsp = dsp;
        ctl_work->ctl = ctl;
        INIT_WORK(&ctl_work->work, wm_adsp_ctl_work);
        schedule_work(&ctl_work->work);
@@ -903,7 +874,7 @@ err_name:
        return ret;
 }
 
-static int wm_adsp_setup_algs(struct wm_adsp *dsp, struct snd_soc_codec *codec)
+static int wm_adsp_setup_algs(struct wm_adsp *dsp)
 {
        struct regmap *regmap = dsp->regmap;
        struct wmfw_adsp1_id_hdr adsp1_id;
@@ -1091,7 +1062,7 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp, struct snd_soc_codec *codec)
                        if (i + 1 < algs) {
                                region->len = be32_to_cpu(adsp1_alg[i + 1].dm);
                                region->len -= be32_to_cpu(adsp1_alg[i].dm);
-                               wm_adsp_create_control(codec, region);
+                               wm_adsp_create_control(dsp, region);
                        } else {
                                adsp_warn(dsp, "Missing length info for region DM with ID %x\n",
                                          be32_to_cpu(adsp1_alg[i].alg.id));
@@ -1108,7 +1079,7 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp, struct snd_soc_codec *codec)
                        if (i + 1 < algs) {
                                region->len = be32_to_cpu(adsp1_alg[i + 1].zm);
                                region->len -= be32_to_cpu(adsp1_alg[i].zm);
-                               wm_adsp_create_control(codec, region);
+                               wm_adsp_create_control(dsp, region);
                        } else {
                                adsp_warn(dsp, "Missing length info for region ZM with ID %x\n",
                                          be32_to_cpu(adsp1_alg[i].alg.id));
@@ -1137,7 +1108,7 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp, struct snd_soc_codec *codec)
                        if (i + 1 < algs) {
                                region->len = be32_to_cpu(adsp2_alg[i + 1].xm);
                                region->len -= be32_to_cpu(adsp2_alg[i].xm);
-                               wm_adsp_create_control(codec, region);
+                               wm_adsp_create_control(dsp, region);
                        } else {
                                adsp_warn(dsp, "Missing length info for region XM with ID %x\n",
                                          be32_to_cpu(adsp2_alg[i].alg.id));
@@ -1154,7 +1125,7 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp, struct snd_soc_codec *codec)
                        if (i + 1 < algs) {
                                region->len = be32_to_cpu(adsp2_alg[i + 1].ym);
                                region->len -= be32_to_cpu(adsp2_alg[i].ym);
-                               wm_adsp_create_control(codec, region);
+                               wm_adsp_create_control(dsp, region);
                        } else {
                                adsp_warn(dsp, "Missing length info for region YM with ID %x\n",
                                          be32_to_cpu(adsp2_alg[i].alg.id));
@@ -1171,7 +1142,7 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp, struct snd_soc_codec *codec)
                        if (i + 1 < algs) {
                                region->len = be32_to_cpu(adsp2_alg[i + 1].zm);
                                region->len -= be32_to_cpu(adsp2_alg[i].zm);
-                               wm_adsp_create_control(codec, region);
+                               wm_adsp_create_control(dsp, region);
                        } else {
                                adsp_warn(dsp, "Missing length info for region ZM with ID %x\n",
                                          be32_to_cpu(adsp2_alg[i].alg.id));
@@ -1391,6 +1362,8 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
        int ret;
        int val;
 
+       dsp->card = codec->card;
+
        switch (event) {
        case SND_SOC_DAPM_POST_PMU:
                regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
@@ -1425,7 +1398,7 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
                if (ret != 0)
                        goto err;
 
-               ret = wm_adsp_setup_algs(dsp, codec);
+               ret = wm_adsp_setup_algs(dsp);
                if (ret != 0)
                        goto err;
 
@@ -1434,12 +1407,12 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
                        goto err;
 
                /* Initialize caches for enabled and unset controls */
-               ret = wm_coeff_init_control_caches(dsp->wm_coeff);
+               ret = wm_coeff_init_control_caches(dsp);
                if (ret != 0)
                        goto err;
 
                /* Sync set controls */
-               ret = wm_coeff_sync_controls(dsp->wm_coeff);
+               ret = wm_coeff_sync_controls(dsp);
                if (ret != 0)
                        goto err;
 
@@ -1460,10 +1433,8 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
                regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
                                   ADSP1_SYS_ENA, 0);
 
-               list_for_each_entry(ctl, &dsp->wm_coeff->ctl_list,
-                                   list) {
+               list_for_each_entry(ctl, &dsp->ctl_list, list)
                        ctl->enabled = 0;
-               }
                break;
 
        default:
@@ -1520,6 +1491,8 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
        unsigned int val;
        int ret;
 
+       dsp->card = codec->card;
+
        switch (event) {
        case SND_SOC_DAPM_POST_PMU:
                /*
@@ -1582,7 +1555,7 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
                if (ret != 0)
                        goto err;
 
-               ret = wm_adsp_setup_algs(dsp, codec);
+               ret = wm_adsp_setup_algs(dsp);
                if (ret != 0)
                        goto err;
 
@@ -1591,12 +1564,12 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
                        goto err;
 
                /* Initialize caches for enabled and unset controls */
-               ret = wm_coeff_init_control_caches(dsp->wm_coeff);
+               ret = wm_coeff_init_control_caches(dsp);
                if (ret != 0)
                        goto err;
 
                /* Sync set controls */
-               ret = wm_coeff_sync_controls(dsp->wm_coeff);
+               ret = wm_coeff_sync_controls(dsp);
                if (ret != 0)
                        goto err;
 
@@ -1637,10 +1610,8 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
                                        ret);
                }
 
-               list_for_each_entry(ctl, &dsp->wm_coeff->ctl_list,
-                                   list) {
+               list_for_each_entry(ctl, &dsp->ctl_list, list)
                        ctl->enabled = 0;
-               }
 
                while (!list_empty(&dsp->alg_regions)) {
                        alg_region = list_first_entry(&dsp->alg_regions,
@@ -1679,49 +1650,38 @@ int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs)
        }
 
        INIT_LIST_HEAD(&adsp->alg_regions);
-
-       adsp->wm_coeff = kzalloc(sizeof(*adsp->wm_coeff),
-                                GFP_KERNEL);
-       if (!adsp->wm_coeff)
-               return -ENOMEM;
-       adsp->wm_coeff->regmap = adsp->regmap;
-       adsp->wm_coeff->dev = adsp->dev;
-       INIT_LIST_HEAD(&adsp->wm_coeff->ctl_list);
+       INIT_LIST_HEAD(&adsp->ctl_list);
 
        if (dvfs) {
                adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD");
                if (IS_ERR(adsp->dvfs)) {
                        ret = PTR_ERR(adsp->dvfs);
                        dev_err(adsp->dev, "Failed to get DCVDD: %d\n", ret);
-                       goto out_coeff;
+                       return ret;
                }
 
                ret = regulator_enable(adsp->dvfs);
                if (ret != 0) {
                        dev_err(adsp->dev, "Failed to enable DCVDD: %d\n",
                                ret);
-                       goto out_coeff;
+                       return ret;
                }
 
                ret = regulator_set_voltage(adsp->dvfs, 1200000, 1800000);
                if (ret != 0) {
                        dev_err(adsp->dev, "Failed to initialise DVFS: %d\n",
                                ret);
-                       goto out_coeff;
+                       return ret;
                }
 
                ret = regulator_disable(adsp->dvfs);
                if (ret != 0) {
                        dev_err(adsp->dev, "Failed to disable DCVDD: %d\n",
                                ret);
-                       goto out_coeff;
+                       return ret;
                }
        }
 
        return 0;
-
-out_coeff:
-       kfree(adsp->wm_coeff);
-       return ret;
 }
 EXPORT_SYMBOL_GPL(wm_adsp2_init);
index 9f922c82536c52f8939db5834bbcfda80e1c5b59..d018dea6254de44c5997813fcb9b958eeca09706 100644 (file)
@@ -39,6 +39,7 @@ struct wm_adsp {
        int type;
        struct device *dev;
        struct regmap *regmap;
+       struct snd_soc_card *card;
 
        int base;
        int sysclk_reg;
@@ -57,7 +58,7 @@ struct wm_adsp {
 
        struct regulator *dvfs;
 
-       struct wm_coeff *wm_coeff;
+       struct list_head ctl_list;
 };
 
 #define WM_ADSP1(wname, num) \
index b5c91f9aa1600611dd4a64ed503511ca0a2e4bfb..046f8778f2b8df3fa51c6eae88ef17a98b45d829 100644 (file)
@@ -2452,6 +2452,22 @@ static int snd_soc_add_controls(struct snd_card *card, struct device *dev,
        return 0;
 }
 
+struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card,
+                                              const char *name)
+{
+       struct snd_card *card = soc_card->snd_card;
+       struct snd_kcontrol *kctl;
+
+       if (unlikely(!name))
+               return NULL;
+
+       list_for_each_entry(kctl, &card->controls, list)
+               if (!strncmp(kctl->id.name, name, sizeof(kctl->id.name)))
+                       return kctl;
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(snd_soc_card_get_kcontrol);
+
 /**
  * snd_soc_add_codec_controls - add an array of controls to a codec.
  * Convenience function to add a list of controls. Many codecs were