[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