diff options
Diffstat (limited to 'sound/soc/codecs/arizona.c')
| -rw-r--r-- | sound/soc/codecs/arizona.c | 78 | 
1 files changed, 69 insertions, 9 deletions
| diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 9550d7433ad0..29202610dd0d 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -84,7 +84,7 @@ static int arizona_spk_ev(struct snd_soc_dapm_widget *w,  			  struct snd_kcontrol *kcontrol,  			  int event)  { -	struct snd_soc_codec *codec = w->codec; +	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);  	struct arizona *arizona = dev_get_drvdata(codec->dev->parent);  	struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);  	bool manual_ena = false; @@ -692,7 +692,8 @@ static void arizona_in_set_vu(struct snd_soc_codec *codec, int ena)  int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,  		  int event)  { -	struct arizona_priv *priv = snd_soc_codec_get_drvdata(w->codec); +	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); +	struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);  	unsigned int reg;  	if (w->shift % 2) @@ -705,25 +706,25 @@ int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,  		priv->in_pending++;  		break;  	case SND_SOC_DAPM_POST_PMU: -		snd_soc_update_bits(w->codec, reg, ARIZONA_IN1L_MUTE, 0); +		snd_soc_update_bits(codec, reg, ARIZONA_IN1L_MUTE, 0);  		/* If this is the last input pending then allow VU */  		priv->in_pending--;  		if (priv->in_pending == 0) {  			msleep(1); -			arizona_in_set_vu(w->codec, 1); +			arizona_in_set_vu(codec, 1);  		}  		break;  	case SND_SOC_DAPM_PRE_PMD: -		snd_soc_update_bits(w->codec, reg, +		snd_soc_update_bits(codec, reg,  				    ARIZONA_IN1L_MUTE | ARIZONA_IN_VU,  				    ARIZONA_IN1L_MUTE | ARIZONA_IN_VU);  		break;  	case SND_SOC_DAPM_POST_PMD:  		/* Disable volume updates if no inputs are enabled */ -		reg = snd_soc_read(w->codec, ARIZONA_INPUT_ENABLES); +		reg = snd_soc_read(codec, ARIZONA_INPUT_ENABLES);  		if (reg == 0) -			arizona_in_set_vu(w->codec, 0); +			arizona_in_set_vu(codec, 0);  	}  	return 0; @@ -734,7 +735,25 @@ int arizona_out_ev(struct snd_soc_dapm_widget *w,  		   struct snd_kcontrol *kcontrol,  		   int event)  { +	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); +	struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); +  	switch (event) { +	case SND_SOC_DAPM_PRE_PMU: +		switch (w->shift) { +		case ARIZONA_OUT1L_ENA_SHIFT: +		case ARIZONA_OUT1R_ENA_SHIFT: +		case ARIZONA_OUT2L_ENA_SHIFT: +		case ARIZONA_OUT2R_ENA_SHIFT: +		case ARIZONA_OUT3L_ENA_SHIFT: +		case ARIZONA_OUT3R_ENA_SHIFT: +			priv->out_up_pending++; +			priv->out_up_delay += 17; +			break; +		default: +			break; +		} +		break;  	case SND_SOC_DAPM_POST_PMU:  		switch (w->shift) {  		case ARIZONA_OUT1L_ENA_SHIFT: @@ -743,13 +762,50 @@ int arizona_out_ev(struct snd_soc_dapm_widget *w,  		case ARIZONA_OUT2R_ENA_SHIFT:  		case ARIZONA_OUT3L_ENA_SHIFT:  		case ARIZONA_OUT3R_ENA_SHIFT: -			msleep(17); +			priv->out_up_pending--; +			if (!priv->out_up_pending) { +				msleep(priv->out_up_delay); +				priv->out_up_delay = 0; +			}  			break;  		default:  			break;  		}  		break; +	case SND_SOC_DAPM_PRE_PMD: +		switch (w->shift) { +		case ARIZONA_OUT1L_ENA_SHIFT: +		case ARIZONA_OUT1R_ENA_SHIFT: +		case ARIZONA_OUT2L_ENA_SHIFT: +		case ARIZONA_OUT2R_ENA_SHIFT: +		case ARIZONA_OUT3L_ENA_SHIFT: +		case ARIZONA_OUT3R_ENA_SHIFT: +			priv->out_down_pending++; +			priv->out_down_delay++; +			break; +		default: +			break; +		} +		break; +	case SND_SOC_DAPM_POST_PMD: +		switch (w->shift) { +		case ARIZONA_OUT1L_ENA_SHIFT: +		case ARIZONA_OUT1R_ENA_SHIFT: +		case ARIZONA_OUT2L_ENA_SHIFT: +		case ARIZONA_OUT2R_ENA_SHIFT: +		case ARIZONA_OUT3L_ENA_SHIFT: +		case ARIZONA_OUT3R_ENA_SHIFT: +			priv->out_down_pending--; +			if (!priv->out_down_pending) { +				msleep(priv->out_down_delay); +				priv->out_down_delay = 0; +			} +			break; +		default: +			break; +		} +		break;  	}  	return 0; @@ -760,7 +816,8 @@ int arizona_hp_ev(struct snd_soc_dapm_widget *w,  		   struct snd_kcontrol *kcontrol,  		   int event)  { -	struct arizona_priv *priv = snd_soc_codec_get_drvdata(w->codec); +	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); +	struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);  	struct arizona *arizona = priv->arizona;  	unsigned int mask = 1 << w->shift;  	unsigned int val; @@ -772,6 +829,9 @@ int arizona_hp_ev(struct snd_soc_dapm_widget *w,  	case SND_SOC_DAPM_PRE_PMD:  		val = 0;  		break; +	case SND_SOC_DAPM_PRE_PMU: +	case SND_SOC_DAPM_POST_PMD: +		return arizona_out_ev(w, kcontrol, event);  	default:  		return -EINVAL;  	} |