diff options
| -rw-r--r-- | sound/soc/codecs/wm_adsp.c | 114 | ||||
| -rw-r--r-- | sound/soc/codecs/wm_adsp.h | 9 | 
2 files changed, 119 insertions, 4 deletions
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 017d5101e78..5015ff287c3 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -378,6 +378,7 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp)  	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; @@ -496,19 +497,80 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp)  	for (i = 0; i < algs; i++) {  		switch (dsp->type) {  		case WMFW_ADSP1: -			adsp_info(dsp, "%d: ID %x v%d.%d.%d\n", +			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].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(®ion->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(®ion->list, +					      &dsp->alg_regions); +			}  			break;  		case WMFW_ADSP2: -			adsp_info(dsp, "%d: ID %x v%d.%d.%d\n", +			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].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(®ion->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(®ion->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(®ion->list, +					      &dsp->alg_regions); +			}  			break;  		}  	} @@ -524,6 +586,8 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)  	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; @@ -588,6 +652,37 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)  			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);  			break; @@ -711,6 +806,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; @@ -811,6 +907,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: @@ -840,6 +944,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)) { diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h index ffd29a4609e..48814198e24 100644 --- a/sound/soc/codecs/wm_adsp.h +++ b/sound/soc/codecs/wm_adsp.h @@ -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; @@ -34,6 +41,8 @@ struct wm_adsp {  	int base; +	struct list_head alg_regions; +  	const struct wm_adsp_region *mem;  	int num_mems;  |