diff options
Diffstat (limited to 'sound/soc/soc-dapm.c')
| -rw-r--r-- | sound/soc/soc-dapm.c | 274 | 
1 files changed, 79 insertions, 195 deletions
| diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index c8a780d0d057..a74b9bf23d9f 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -254,7 +254,6 @@ static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget,  static void dapm_kcontrol_free(struct snd_kcontrol *kctl)  {  	struct dapm_kcontrol_data *data = snd_kcontrol_chip(kctl); -	kfree(data->widget);  	kfree(data->wlist);  	kfree(data);  } @@ -379,86 +378,24 @@ static void dapm_reset(struct snd_soc_card *card)  static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg,  	unsigned int *value)  { -	if (w->codec) { -		*value = snd_soc_read(w->codec, reg); -		return 0; -	} else if (w->platform) { -		*value = snd_soc_platform_read(w->platform, reg); -		return 0; -	} - -	dev_err(w->dapm->dev, "ASoC: no valid widget read method\n"); -	return -1; -} - -static int soc_widget_write(struct snd_soc_dapm_widget *w, int reg, -	unsigned int val) -{ -	if (w->codec) -		return snd_soc_write(w->codec, reg, val); -	else if (w->platform) -		return snd_soc_platform_write(w->platform, reg, val); - -	dev_err(w->dapm->dev, "ASoC: no valid widget write method\n"); -	return -1; -} - -static inline void soc_widget_lock(struct snd_soc_dapm_widget *w) -{ -	if (w->codec && !w->codec->using_regmap) -		mutex_lock(&w->codec->mutex); -	else if (w->platform) -		mutex_lock(&w->platform->mutex); +	if (!w->dapm->component) +		return -EIO; +	return snd_soc_component_read(w->dapm->component, reg, value);  } -static inline void soc_widget_unlock(struct snd_soc_dapm_widget *w) +static int soc_widget_update_bits(struct snd_soc_dapm_widget *w, +	int reg, unsigned int mask, unsigned int value)  { -	if (w->codec && !w->codec->using_regmap) -		mutex_unlock(&w->codec->mutex); -	else if (w->platform) -		mutex_unlock(&w->platform->mutex); +	if (!w->dapm->component) +		return -EIO; +	return snd_soc_component_update_bits_async(w->dapm->component, reg, +		mask, value);  }  static void soc_dapm_async_complete(struct snd_soc_dapm_context *dapm)  { -	if (dapm->codec && dapm->codec->using_regmap) -		regmap_async_complete(dapm->codec->control_data); -} - -static int soc_widget_update_bits_locked(struct snd_soc_dapm_widget *w, -	unsigned short reg, unsigned int mask, unsigned int value) -{ -	bool change; -	unsigned int old, new; -	int ret; - -	if (w->codec && w->codec->using_regmap) { -		ret = regmap_update_bits_check_async(w->codec->control_data, -						     reg, mask, value, -						     &change); -		if (ret != 0) -			return ret; -	} else { -		soc_widget_lock(w); -		ret = soc_widget_read(w, reg, &old); -		if (ret < 0) { -			soc_widget_unlock(w); -			return ret; -		} - -		new = (old & ~mask) | (value & mask); -		change = old != new; -		if (change) { -			ret = soc_widget_write(w, reg, new); -			if (ret < 0) { -				soc_widget_unlock(w); -				return ret; -			} -		} -		soc_widget_unlock(w); -	} - -	return change; +	if (dapm->component) +		snd_soc_component_async_complete(dapm->component);  }  /** @@ -1121,26 +1058,6 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,  }  /* - * Handler for generic register modifier widget. - */ -int dapm_reg_event(struct snd_soc_dapm_widget *w, -		   struct snd_kcontrol *kcontrol, int event) -{ -	unsigned int val; - -	if (SND_SOC_DAPM_EVENT_ON(event)) -		val = w->on_val; -	else -		val = w->off_val; - -	soc_widget_update_bits_locked(w, -(w->reg + 1), -			    w->mask << w->shift, val << w->shift); - -	return 0; -} -EXPORT_SYMBOL_GPL(dapm_reg_event); - -/*   * Handler for regulator supply widget.   */  int dapm_regulator_event(struct snd_soc_dapm_widget *w, @@ -1429,7 +1346,7 @@ static void dapm_seq_run_coalesced(struct snd_soc_card *card,  			"pop test : Applying 0x%x/0x%x to %x in %dms\n",  			value, mask, reg, card->pop_time);  		pop_wait(card->pop_time); -		soc_widget_update_bits_locked(w, reg, mask, value); +		soc_widget_update_bits(w, reg, mask, value);  	}  	list_for_each_entry(w, pending, power_list) { @@ -1575,8 +1492,7 @@ static void dapm_widget_update(struct snd_soc_card *card)  	if (!w)  		return; -	ret = soc_widget_update_bits_locked(w, update->reg, update->mask, -				  update->val); +	ret = soc_widget_update_bits(w, update->reg, update->mask, update->val);  	if (ret < 0)  		dev_err(w->dapm->dev, "ASoC: %s DAPM update failed: %d\n",  			w->name, ret); @@ -1613,8 +1529,11 @@ static void dapm_pre_sequence_async(void *data, async_cookie_t cookie)  				"ASoC: Failed to turn on bias: %d\n", ret);  	} -	/* Prepare for a STADDBY->ON or ON->STANDBY transition */ -	if (d->bias_level != d->target_bias_level) { +	/* Prepare for a transition to ON or away from ON */ +	if ((d->target_bias_level == SND_SOC_BIAS_ON && +	     d->bias_level != SND_SOC_BIAS_ON) || +	    (d->target_bias_level != SND_SOC_BIAS_ON && +	     d->bias_level == SND_SOC_BIAS_ON)) {  		ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_PREPARE);  		if (ret != 0)  			dev_err(d->dev, @@ -2444,8 +2363,7 @@ err:  }  static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm, -				  const struct snd_soc_dapm_route *route, -				  unsigned int is_prefixed) +				  const struct snd_soc_dapm_route *route)  {  	struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w;  	struct snd_soc_dapm_widget *wtsource = NULL, *wtsink = NULL; @@ -2455,7 +2373,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,  	char prefixed_source[80];  	int ret; -	if (dapm->codec && dapm->codec->name_prefix && !is_prefixed) { +	if (dapm->codec && dapm->codec->name_prefix) {  		snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s",  			 dapm->codec->name_prefix, route->sink);  		sink = prefixed_sink; @@ -2583,7 +2501,7 @@ int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm,  	mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);  	for (i = 0; i < num; i++) { -		r = snd_soc_dapm_add_route(dapm, route, false); +		r = snd_soc_dapm_add_route(dapm, route);  		if (r < 0) {  			dev_err(dapm->dev, "ASoC: Failed to add route %s -> %s -> %s\n",  				route->source, @@ -2855,22 +2773,19 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,  	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);  	change = dapm_kcontrol_set_value(kcontrol, val); - -	if (reg != SND_SOC_NOPM) { -		mask = mask << shift; -		val = val << shift; - -		change = snd_soc_test_bits(codec, reg, mask, val); -	} -  	if (change) {  		if (reg != SND_SOC_NOPM) { -			update.kcontrol = kcontrol; -			update.reg = reg; -			update.mask = mask; -			update.val = val; +			mask = mask << shift; +			val = val << shift; + +			if (snd_soc_test_bits(codec, reg, mask, val)) { +				update.kcontrol = kcontrol; +				update.reg = reg; +				update.mask = mask; +				update.val = val; +				card->update = &update; +			} -			card->update = &update;  		}  		ret = soc_dapm_mixer_update_power(card, kcontrol, connect); @@ -3309,11 +3224,11 @@ int snd_soc_dapm_new_pcm(struct snd_soc_card *card,  			 struct snd_soc_dapm_widget *source,  			 struct snd_soc_dapm_widget *sink)  { -	struct snd_soc_dapm_route routes[2];  	struct snd_soc_dapm_widget template;  	struct snd_soc_dapm_widget *w;  	size_t len;  	char *link_name; +	int ret;  	len = strlen(source->name) + strlen(sink->name) + 2;  	link_name = devm_kzalloc(card->dev, len, GFP_KERNEL); @@ -3340,15 +3255,10 @@ int snd_soc_dapm_new_pcm(struct snd_soc_card *card,  	w->params = params; -	memset(&routes, 0, sizeof(routes)); - -	routes[0].source = source->name; -	routes[0].sink = link_name; -	routes[1].source = link_name; -	routes[1].sink = sink->name; - -	return snd_soc_dapm_add_routes(&card->dapm, routes, -				       ARRAY_SIZE(routes)); +	ret = snd_soc_dapm_add_path(&card->dapm, source, w, NULL, NULL); +	if (ret) +		return ret; +	return snd_soc_dapm_add_path(&card->dapm, w, sink, NULL, NULL);  }  int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm, @@ -3406,6 +3316,7 @@ int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm,  int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card)  {  	struct snd_soc_dapm_widget *dai_w, *w; +	struct snd_soc_dapm_widget *src, *sink;  	struct snd_soc_dai *dai;  	/* For each DAI widget... */ @@ -3436,25 +3347,15 @@ int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card)  			if (!w->sname || !strstr(w->sname, dai_w->name))  				continue; -			if (dai->driver->playback.stream_name && -			    strstr(w->sname, -				   dai->driver->playback.stream_name)) { -				dev_dbg(dai->dev, "%s -> %s\n", -					 dai->playback_widget->name, w->name); - -				snd_soc_dapm_add_path(w->dapm, -					dai->playback_widget, w, NULL, NULL); -			} - -			if (dai->driver->capture.stream_name && -			    strstr(w->sname, -				   dai->driver->capture.stream_name)) { -				dev_dbg(dai->dev, "%s -> %s\n", -					w->name, dai->capture_widget->name); - -				snd_soc_dapm_add_path(w->dapm, w, -					dai->capture_widget, NULL, NULL); +			if (dai_w->id == snd_soc_dapm_dai_in) { +				src = dai_w; +				sink = w; +			} else { +				src = w; +				sink = dai_w;  			} +			dev_dbg(dai->dev, "%s -> %s\n", src->name, sink->name); +			snd_soc_dapm_add_path(w->dapm, src, sink, NULL, NULL);  		}  	} @@ -3464,20 +3365,21 @@ int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card)  void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card)  {  	struct snd_soc_pcm_runtime *rtd = card->rtd; +	struct snd_soc_dapm_widget *sink, *source;  	struct snd_soc_dai *cpu_dai, *codec_dai; -	struct snd_soc_dapm_route r;  	int i; -	memset(&r, 0, sizeof(r)); -  	/* for each BE DAI link... */  	for (i = 0; i < card->num_rtd; i++) {  		rtd = &card->rtd[i];  		cpu_dai = rtd->cpu_dai;  		codec_dai = rtd->codec_dai; -		/* dynamic FE links have no fixed DAI mapping */ -		if (rtd->dai_link->dynamic) +		/* +		 * dynamic FE links have no fixed DAI mapping. +		 * CODEC<->CODEC links have no direct connection. +		 */ +		if (rtd->dai_link->dynamic || rtd->dai_link->params)  			continue;  		/* there is no point in connecting BE DAI links with dummies */ @@ -3487,55 +3389,49 @@ void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card)  		/* connect BE DAI playback if widgets are valid */  		if (codec_dai->playback_widget && cpu_dai->playback_widget) { -			r.source = cpu_dai->playback_widget->name; -			r.sink = codec_dai->playback_widget->name; +			source = cpu_dai->playback_widget; +			sink = codec_dai->playback_widget;  			dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n", -				cpu_dai->codec->name, r.source, -				codec_dai->platform->name, r.sink); +				cpu_dai->codec->name, source->name, +				codec_dai->platform->name, sink->name); -			snd_soc_dapm_add_route(&card->dapm, &r, true); +			snd_soc_dapm_add_path(&card->dapm, source, sink, +				NULL, NULL);  		}  		/* connect BE DAI capture if widgets are valid */  		if (codec_dai->capture_widget && cpu_dai->capture_widget) { -			r.source = codec_dai->capture_widget->name; -			r.sink = cpu_dai->capture_widget->name; +			source = codec_dai->capture_widget; +			sink = cpu_dai->capture_widget;  			dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n", -				codec_dai->codec->name, r.source, -				cpu_dai->platform->name, r.sink); +				codec_dai->codec->name, source->name, +				cpu_dai->platform->name, sink->name); -			snd_soc_dapm_add_route(&card->dapm, &r, true); +			snd_soc_dapm_add_path(&card->dapm, source, sink, +				NULL, NULL);  		} -  	}  } -static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream, +static void soc_dapm_dai_stream_event(struct snd_soc_dai *dai, int stream,  	int event)  { +	struct snd_soc_dapm_widget *w; -	struct snd_soc_dapm_widget *w_cpu, *w_codec; -	struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -	struct snd_soc_dai *codec_dai = rtd->codec_dai; - -	if (stream == SNDRV_PCM_STREAM_PLAYBACK) { -		w_cpu = cpu_dai->playback_widget; -		w_codec = codec_dai->playback_widget; -	} else { -		w_cpu = cpu_dai->capture_widget; -		w_codec = codec_dai->capture_widget; -	} - -	if (w_cpu) { +	if (stream == SNDRV_PCM_STREAM_PLAYBACK) +		w = dai->playback_widget; +	else +		w = dai->capture_widget; -		dapm_mark_dirty(w_cpu, "stream event"); +	if (w) { +		dapm_mark_dirty(w, "stream event");  		switch (event) {  		case SND_SOC_DAPM_STREAM_START: -			w_cpu->active = 1; +			w->active = 1;  			break;  		case SND_SOC_DAPM_STREAM_STOP: -			w_cpu->active = 0; +			w->active = 0;  			break;  		case SND_SOC_DAPM_STREAM_SUSPEND:  		case SND_SOC_DAPM_STREAM_RESUME: @@ -3544,25 +3440,13 @@ static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,  			break;  		}  	} +} -	if (w_codec) { - -		dapm_mark_dirty(w_codec, "stream event"); - -		switch (event) { -		case SND_SOC_DAPM_STREAM_START: -			w_codec->active = 1; -			break; -		case SND_SOC_DAPM_STREAM_STOP: -			w_codec->active = 0; -			break; -		case SND_SOC_DAPM_STREAM_SUSPEND: -		case SND_SOC_DAPM_STREAM_RESUME: -		case SND_SOC_DAPM_STREAM_PAUSE_PUSH: -		case SND_SOC_DAPM_STREAM_PAUSE_RELEASE: -			break; -		} -	} +static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream, +	int event) +{ +	soc_dapm_dai_stream_event(rtd->cpu_dai, stream, event); +	soc_dapm_dai_stream_event(rtd->codec_dai, stream, event);  	dapm_power_widgets(rtd->card, event);  } | 
