[alsa-devel] [PATCH 2/3] ASoC: wm_adsp: Add support for grouped ALSA binary controls
Takashi Iwai
tiwai at suse.de
Thu Oct 31 08:55:53 CET 2013
At Wed, 30 Oct 2013 16:54:29 +0000,
Dimitris Papastamos wrote:
>
> Currently the ALSA ABI imposes a hard limit of 512 bytes per binary
> control. To support coefficient data blocks of larger sizes we carve up
> this space into multiple alsa controls. All of these controls are
> identified by a common prefix and suffix of the form ":<blk id>".
>
> Control groupings can also consist of a single block in which case the
> suffix ":0" is used.
Why not using the control element index?
You can create each kctl element individually with a different index,
but also you can create multiple ctl elements in a single shot by
passing to snd_kcontrol_new.count field. This will create a grouped
object, thus it saves spaces, too, in comparison with individual
kctls. The drawback is that you need to retrieve the real index via
snd_ctl_get_ioff*() in each control callback.
Takashi
>
> Change-Id: Ib8560bbd98425b1732b2ccf372a53102bdeb7d7f
> Signed-off-by: Dimitris Papastamos <dp at opensource.wolfsonmicro.com>
> ---
> sound/soc/codecs/wm_adsp.c | 59 +++++++++++++++++++++++++++++++++++++++-------
> sound/soc/codecs/wm_adsp.h | 1 +
> 2 files changed, 52 insertions(+), 8 deletions(-)
>
> diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
> index cd007cc..b3fbe4a 100644
> --- a/sound/soc/codecs/wm_adsp.c
> +++ b/sound/soc/codecs/wm_adsp.c
> @@ -714,7 +714,6 @@ static void wm_adsp_ctl_work(struct work_struct *work)
>
> static int wm_adsp_create_control(struct wm_adsp *dsp,
> const struct wm_adsp_alg_region *region)
> -
> {
> struct wm_coeff_ctl *ctl;
> struct wmfw_ctl_work *ctl_work;
> @@ -746,8 +745,8 @@ static int wm_adsp_create_control(struct wm_adsp *dsp,
> return -EINVAL;
> }
>
> - snprintf(name, PAGE_SIZE, "DSP%d %s %x",
> - dsp->num, region_name, region->alg);
> + snprintf(name, PAGE_SIZE, "DSP%d %s %x:%d",
> + dsp->num, region_name, region->alg, region->block);
>
> list_for_each_entry(ctl, &dsp->ctl_list,
> list) {
> @@ -808,6 +807,50 @@ err_name:
> return ret;
> }
>
> +static int wm_adsp_create_grouped_control(struct wm_adsp *dsp,
> + struct wm_adsp_alg_region *region)
> +{
> + size_t len = region->len, offset = 0;
> + struct wm_adsp_alg_region *r;
> + int ret;
> +
> + region->block = 0;
> + /* This is the quick case for control groups of a single block */
> + if (region->len <= 512)
> + return wm_adsp_create_control(dsp, region);
> +
> + /* The passed `region' is already in the list
> + * of algorithm regions so just create the control for it and don't
> + * add it to the list */
> + region->len = 512;
> + ret = wm_adsp_create_control(dsp, region);
> + if (ret < 0)
> + return ret;
> + offset += 512;
> +
> + /* Carve up the entire region into 512-byte chunks */
> + do {
> + r = kzalloc(sizeof(*r), GFP_KERNEL);
> + if (!r)
> + return -ENOMEM;
> + r->block = offset / 512;
> + r->type = region->type;
> + r->alg = region->alg;
> + r->base = region->base + offset;
> + if (len - offset > 512)
> + r->len = 512;
> + else
> + r->len = len - offset;
> + offset += r->len;
> + list_add_tail(&r->list, &dsp->alg_regions);
> + ret = wm_adsp_create_control(dsp, r);
> + if (ret < 0)
> + return ret;
> + } while (offset < len);
> +
> + return 0;
> +}
> +
> static int wm_adsp_setup_algs(struct wm_adsp *dsp)
> {
> struct regmap *regmap = dsp->regmap;
> @@ -983,7 +1026,7 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp)
> 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(dsp, region);
> + wm_adsp_create_grouped_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));
> @@ -1000,7 +1043,7 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp)
> 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(dsp, region);
> + wm_adsp_create_grouped_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));
> @@ -1029,7 +1072,7 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp)
> 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(dsp, region);
> + wm_adsp_create_grouped_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));
> @@ -1046,7 +1089,7 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp)
> 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(dsp, region);
> + wm_adsp_create_grouped_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));
> @@ -1063,7 +1106,7 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp)
> 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(dsp, region);
> + wm_adsp_create_grouped_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));
> diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h
> index 7603167..60a7482 100644
> --- a/sound/soc/codecs/wm_adsp.h
> +++ b/sound/soc/codecs/wm_adsp.h
> @@ -27,6 +27,7 @@ struct wm_adsp_region {
>
> struct wm_adsp_alg_region {
> struct list_head list;
> + unsigned int block;
> unsigned int alg;
> int type;
> unsigned int base;
> --
> 1.8.4.2
>
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel at alsa-project.org
> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
>
More information about the Alsa-devel
mailing list