diff options
Diffstat (limited to 'sound/soc/codecs/wcd934x.c')
| -rw-r--r-- | sound/soc/codecs/wcd934x.c | 135 | 
1 files changed, 96 insertions, 39 deletions
| diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c index c496b359f2f4..6c468527fec6 100644 --- a/sound/soc/codecs/wcd934x.c +++ b/sound/soc/codecs/wcd934x.c @@ -1896,9 +1896,8 @@ static int wcd934x_hw_params(struct snd_pcm_substream *substream,  	}  	wcd->dai[dai->id].sconfig.rate = params_rate(params); -	wcd934x_slim_set_hw_params(wcd, &wcd->dai[dai->id], substream->stream); -	return 0; +	return wcd934x_slim_set_hw_params(wcd, &wcd->dai[dai->id], substream->stream);  }  static int wcd934x_hw_free(struct snd_pcm_substream *substream, @@ -3257,6 +3256,9 @@ static int wcd934x_compander_set(struct snd_kcontrol *kc,  	int value = ucontrol->value.integer.value[0];  	int sel; +	if (wcd->comp_enabled[comp] == value) +		return 0; +  	wcd->comp_enabled[comp] = value;  	sel = value ? WCD934X_HPH_GAIN_SRC_SEL_COMPANDER :  		WCD934X_HPH_GAIN_SRC_SEL_REGISTER; @@ -3280,10 +3282,10 @@ static int wcd934x_compander_set(struct snd_kcontrol *kc,  	case COMPANDER_8:  		break;  	default: -		break; +		return 0;  	} -	return 0; +	return 1;  }  static int wcd934x_rx_hph_mode_get(struct snd_kcontrol *kc, @@ -3327,6 +3329,31 @@ static int slim_rx_mux_get(struct snd_kcontrol *kc,  	return 0;  } +static int slim_rx_mux_to_dai_id(int mux) +{ +	int aif_id; + +	switch (mux) { +	case 1: +		aif_id = AIF1_PB; +		break; +	case 2: +		aif_id = AIF2_PB; +		break; +	case 3: +		aif_id = AIF3_PB; +		break; +	case 4: +		aif_id = AIF4_PB; +		break; +	default: +		aif_id = -1; +		break; +	} + +	return aif_id; +} +  static int slim_rx_mux_put(struct snd_kcontrol *kc,  			   struct snd_ctl_elem_value *ucontrol)  { @@ -3334,43 +3361,59 @@ static int slim_rx_mux_put(struct snd_kcontrol *kc,  	struct wcd934x_codec *wcd = dev_get_drvdata(w->dapm->dev);  	struct soc_enum *e = (struct soc_enum *)kc->private_value;  	struct snd_soc_dapm_update *update = NULL; +	struct wcd934x_slim_ch *ch, *c;  	u32 port_id = w->shift; +	bool found = false; +	int mux_idx; +	int prev_mux_idx = wcd->rx_port_value[port_id]; +	int aif_id; -	if (wcd->rx_port_value[port_id] == ucontrol->value.enumerated.item[0]) -		return 0; +	mux_idx = ucontrol->value.enumerated.item[0]; -	wcd->rx_port_value[port_id] = ucontrol->value.enumerated.item[0]; +	if (mux_idx == prev_mux_idx) +		return 0; -	switch (wcd->rx_port_value[port_id]) { +	switch(mux_idx) {  	case 0: -		list_del_init(&wcd->rx_chs[port_id].list); -		break; -	case 1: -		list_add_tail(&wcd->rx_chs[port_id].list, -			      &wcd->dai[AIF1_PB].slim_ch_list); -		break; -	case 2: -		list_add_tail(&wcd->rx_chs[port_id].list, -			      &wcd->dai[AIF2_PB].slim_ch_list); -		break; -	case 3: -		list_add_tail(&wcd->rx_chs[port_id].list, -			      &wcd->dai[AIF3_PB].slim_ch_list); +		aif_id = slim_rx_mux_to_dai_id(prev_mux_idx); +		if (aif_id < 0) +			return 0; + +		list_for_each_entry_safe(ch, c, &wcd->dai[aif_id].slim_ch_list, list) { +			if (ch->port == port_id + WCD934X_RX_START) { +				found = true; +				list_del_init(&ch->list); +				break; +			} +		} +		if (!found) +			return 0; +  		break; -	case 4: -		list_add_tail(&wcd->rx_chs[port_id].list, -			      &wcd->dai[AIF4_PB].slim_ch_list); +	case 1 ... 4: +		aif_id = slim_rx_mux_to_dai_id(mux_idx); +		if (aif_id < 0) +			return 0; + +		if (list_empty(&wcd->rx_chs[port_id].list)) { +			list_add_tail(&wcd->rx_chs[port_id].list, +				      &wcd->dai[aif_id].slim_ch_list); +		} else { +			dev_err(wcd->dev ,"SLIM_RX%d PORT is busy\n", port_id); +			return 0; +		}  		break; +  	default: -		dev_err(wcd->dev, "Unknown AIF %d\n", -			wcd->rx_port_value[port_id]); +		dev_err(wcd->dev, "Unknown AIF %d\n", mux_idx);  		goto err;  	} +	wcd->rx_port_value[port_id] = mux_idx;  	snd_soc_dapm_mux_update_power(w->dapm, kc, wcd->rx_port_value[port_id],  				      e, update); -	return 0; +	return 1;  err:  	return -EINVAL;  } @@ -3380,7 +3423,7 @@ static int wcd934x_int_dem_inp_mux_put(struct snd_kcontrol *kc,  {  	struct soc_enum *e = (struct soc_enum *)kc->private_value;  	struct snd_soc_component *component; -	int reg, val, ret; +	int reg, val;  	component = snd_soc_dapm_kcontrol_component(kc);  	val = ucontrol->value.enumerated.item[0]; @@ -3403,9 +3446,7 @@ static int wcd934x_int_dem_inp_mux_put(struct snd_kcontrol *kc,  					      WCD934X_RX_DLY_ZN_EN_MASK,  					      WCD934X_RX_DLY_ZN_DISABLE); -	ret = snd_soc_dapm_put_enum_double(kc, ucontrol); - -	return ret; +	return snd_soc_dapm_put_enum_double(kc, ucontrol);  }  static int wcd934x_dec_enum_put(struct snd_kcontrol *kcontrol, @@ -3816,6 +3857,7 @@ static int slim_tx_mixer_put(struct snd_kcontrol *kc,  	struct soc_mixer_control *mixer =  			(struct soc_mixer_control *)kc->private_value;  	int enable = ucontrol->value.integer.value[0]; +	struct wcd934x_slim_ch *ch, *c;  	int dai_id = widget->shift;  	int port_id = mixer->shift; @@ -3823,17 +3865,32 @@ static int slim_tx_mixer_put(struct snd_kcontrol *kc,  	if (enable == wcd->tx_port_value[port_id])  		return 0; -	wcd->tx_port_value[port_id] = enable; - -	if (enable) -		list_add_tail(&wcd->tx_chs[port_id].list, -			      &wcd->dai[dai_id].slim_ch_list); -	else -		list_del_init(&wcd->tx_chs[port_id].list); +	if (enable) { +		if (list_empty(&wcd->tx_chs[port_id].list)) { +			list_add_tail(&wcd->tx_chs[port_id].list, +				      &wcd->dai[dai_id].slim_ch_list); +		} else { +			dev_err(wcd->dev ,"SLIM_TX%d PORT is busy\n", port_id); +			return 0; +		} +	 } else { +		bool found = false; + +		list_for_each_entry_safe(ch, c, &wcd->dai[dai_id].slim_ch_list, list) { +			if (ch->port == port_id) { +				found = true; +				list_del_init(&wcd->tx_chs[port_id].list); +				break; +			} +		} +		if (!found) +			return 0; +	 } +	wcd->tx_port_value[port_id] = enable;  	snd_soc_dapm_mixer_update_power(widget->dapm, kc, enable, update); -	return 0; +	return 1;  }  static const struct snd_kcontrol_new aif1_slim_cap_mixer[] = { |