All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] ASoC: rt5640: change widget sequence for depop
@ 2013-08-05  4:19 bardliao
  2013-08-05 14:48 ` Mark Brown
                   ` (2 more replies)
  0 siblings, 3 replies; 35+ messages in thread
From: bardliao @ 2013-08-05  4:19 UTC (permalink / raw)
  To: broonie, lgirdwood
  Cc: oder_chiou, alsa-devel, swarren, swarren, bardliao, flove

From: Bard Liao <bardliao@realtek.com>

Add mute/unmute control in widget event and modify the power on/off sequence to avoid pop noise.

Signed-off-by: Bard Liao <bardliao@realtek.com>
---
Please ignore the previous patch.
I have tested speaker and headphone playback on this patch.
---
 sound/soc/codecs/rt5640.c | 389 +++++++++++++++++++++++++++++++++++++++-------
 sound/soc/codecs/rt5640.h |  15 ++
 2 files changed, 352 insertions(+), 52 deletions(-)

diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index 4db7314..cae3f46 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -50,8 +50,6 @@ static const struct regmap_range_cfg rt5640_ranges[] = {
 
 static struct reg_default init_list[] = {
 	{RT5640_PR_BASE + 0x3d,	0x3600},
-	{RT5640_PR_BASE + 0x1c,	0x0D21},
-	{RT5640_PR_BASE + 0x1b,	0x0000},
 	{RT5640_PR_BASE + 0x12,	0x0aa8},
 	{RT5640_PR_BASE + 0x14,	0x0aaa},
 	{RT5640_PR_BASE + 0x20,	0x6110},
@@ -378,21 +376,119 @@ static const SOC_ENUM_SINGLE_DECL(rt5640_if2_adc_enum, RT5640_DIG_INF_DATA,
 static const char * const rt5640_clsd_spk_ratio[] = {"1.66x", "1.83x", "1.94x",
 	"2x", "2.11x", "2.22x", "2.33x", "2.44x", "2.55x", "2.66x", "2.77x"};
 
+static const char * const rt5640_mute_mode[] = {"mute", "unmute"};
+
+static const SOC_ENUM_SINGLE_DECL(rt5640_hp_enum, 0, 0, rt5640_mute_mode);
+static const SOC_ENUM_SINGLE_DECL(rt5640_spo_enum, 0, 0, rt5640_mute_mode);
+
 static const SOC_ENUM_SINGLE_DECL(
 	rt5640_clsd_spk_ratio_enum, RT5640_CLS_D_OUT,
 	RT5640_CLSD_RATIO_SFT, rt5640_clsd_spk_ratio);
 
+static int rt5640_spo_get(struct snd_kcontrol *kcontrol,
+			   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
+
+	ucontrol->value.integer.value[0] = !rt5640->spo_l_mute;
+	ucontrol->value.integer.value[1] = !rt5640->spo_r_mute;
+
+	return 0;
+}
+
+static int rt5640_spo_put(struct snd_kcontrol *kcontrol,
+			   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
+	unsigned int pow;
+
+	pow = snd_soc_read(codec, RT5640_PWR_DIG1) & RT5640_PWR_CLS_D;
+
+	if (ucontrol->value.integer.value[0]) {
+		rt5640->spo_l_mute = false;
+		if (pow)
+			snd_soc_update_bits(codec, RT5640_SPK_VOL,
+				    RT5640_L_MUTE, 0);
+	} else {
+		rt5640->spo_l_mute = true;
+		snd_soc_update_bits(codec, RT5640_SPK_VOL,
+				    RT5640_L_MUTE,
+				    RT5640_L_MUTE);
+	}
+	if (ucontrol->value.integer.value[1]) {
+		rt5640->spo_r_mute = false;
+		if (pow)
+			snd_soc_update_bits(codec, RT5640_SPK_VOL,
+				    RT5640_R_MUTE, 0);
+	} else {
+		rt5640->spo_r_mute = true;
+		snd_soc_update_bits(codec, RT5640_SPK_VOL,
+				    RT5640_R_MUTE,
+				    RT5640_R_MUTE);
+	}
+
+	return 0;
+}
+
+static int rt5640_hp_get(struct snd_kcontrol *kcontrol,
+			   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
+
+	ucontrol->value.integer.value[0] = !rt5640->hp_l_mute;
+	ucontrol->value.integer.value[1] = !rt5640->hp_r_mute;
+
+	return 0;
+}
+
+static int rt5640_hp_put(struct snd_kcontrol *kcontrol,
+			   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
+	unsigned int pow;
+
+	pow = snd_soc_read(codec,  RT5640_PWR_ANLG1);
+
+	if (ucontrol->value.integer.value[0]) {
+		rt5640->hp_l_mute = false;
+		if (pow & RT5640_PWR_HP_L)
+			snd_soc_update_bits(codec, RT5640_HP_VOL,
+				RT5640_L_MUTE, 0);
+	} else {
+		rt5640->hp_l_mute = true;
+		snd_soc_update_bits(codec, RT5640_HP_VOL,
+			RT5640_L_MUTE, RT5640_L_MUTE);
+	}
+	if (ucontrol->value.integer.value[1]) {
+		rt5640->hp_r_mute = false;
+		if (pow & RT5640_PWR_HP_R)
+			snd_soc_update_bits(codec, RT5640_HP_VOL,
+				RT5640_R_MUTE, 0);
+	} else {
+		rt5640->hp_r_mute = true;
+		snd_soc_update_bits(codec, RT5640_HP_VOL,
+			RT5640_R_MUTE, RT5640_R_MUTE);
+	}
+
+
+	return 0;
+}
+
 static const struct snd_kcontrol_new rt5640_snd_controls[] = {
 	/* Speaker Output Volume */
-	SOC_DOUBLE("Speaker Playback Switch", RT5640_SPK_VOL,
-		RT5640_L_MUTE_SFT, RT5640_R_MUTE_SFT, 1, 1),
+	SOC_DOUBLE_EXT("Speaker Playback Switch", SND_SOC_NOPM,
+		0, 1, 1, 0, rt5640_spo_get, rt5640_spo_put),
 	SOC_DOUBLE("Speaker Channel Switch", RT5640_SPK_VOL,
 		RT5640_VOL_L_SFT, RT5640_VOL_R_SFT, 1, 1),
 	SOC_DOUBLE_TLV("Speaker Playback Volume", RT5640_SPK_VOL,
 		RT5640_L_VOL_SFT, RT5640_R_VOL_SFT, 39, 1, out_vol_tlv),
 	/* Headphone Output Volume */
-	SOC_DOUBLE("HP Playback Switch", RT5640_HP_VOL,
-		RT5640_L_MUTE_SFT, RT5640_R_MUTE_SFT, 1, 1),
+	SOC_DOUBLE_EXT("HP Playback Switch", SND_SOC_NOPM,
+		0, 1, 1, 0, rt5640_hp_get, rt5640_hp_put),
 	SOC_DOUBLE("HP Channel Switch", RT5640_HP_VOL,
 		RT5640_VOL_L_SFT, RT5640_VOL_R_SFT, 1, 1),
 	SOC_DOUBLE_TLV("HP Playback Volume", RT5640_HP_VOL,
@@ -868,33 +964,6 @@ static const SOC_ENUM_SINGLE_DECL(
 static const struct snd_kcontrol_new rt5640_sdi_mux =
 	SOC_DAPM_ENUM("SDI select", rt5640_sdi_sel_enum);
 
-static int spk_event(struct snd_soc_dapm_widget *w,
-	struct snd_kcontrol *kcontrol, int event)
-{
-	struct snd_soc_codec *codec = w->codec;
-	struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
-
-	switch (event) {
-	case SND_SOC_DAPM_POST_PMU:
-		regmap_update_bits(rt5640->regmap, RT5640_PWR_DIG1,
-					0x0001, 0x0001);
-		regmap_update_bits(rt5640->regmap, RT5640_PR_BASE + 0x1c,
-					0xf000, 0xf000);
-		break;
-
-	case SND_SOC_DAPM_PRE_PMD:
-		regmap_update_bits(rt5640->regmap, RT5640_PR_BASE + 0x1c,
-					0xf000, 0x0000);
-		regmap_update_bits(rt5640->regmap, RT5640_PWR_DIG1,
-					0x0001, 0x0000);
-		break;
-
-	default:
-		return 0;
-	}
-	return 0;
-}
-
 static int rt5640_set_dmic1_event(struct snd_soc_dapm_widget *w,
 	struct snd_kcontrol *kcontrol, int event)
 {
@@ -943,6 +1012,216 @@ static int rt5640_set_dmic2_event(struct snd_soc_dapm_widget *w,
 	return 0;
 }
 
+static int rt5640_spo_r_event(struct snd_soc_dapm_widget *w,
+			    struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		if (!rt5640->spo_r_mute)
+			snd_soc_update_bits(codec, RT5640_SPK_VOL,
+					    RT5640_R_MUTE, 0);
+		break;
+
+	case SND_SOC_DAPM_PRE_PMD:
+		snd_soc_update_bits(codec, RT5640_SPK_VOL,
+				    RT5640_R_MUTE,
+				    RT5640_R_MUTE);
+		break;
+
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
+static int rt5640_spo_l_event(struct snd_soc_dapm_widget *w,
+			    struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		if (!rt5640->spo_l_mute)
+			snd_soc_update_bits(codec, RT5640_SPK_VOL,
+					    RT5640_L_MUTE, 0);
+		break;
+
+	case SND_SOC_DAPM_PRE_PMD:
+		snd_soc_update_bits(codec, RT5640_SPK_VOL,
+				    RT5640_L_MUTE, RT5640_L_MUTE);
+		break;
+
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
+void hp_amp_power_on(struct snd_soc_codec *codec)
+{
+	struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
+	/* depop parameters */
+	regmap_update_bits(rt5640->regmap, RT5640_PR_BASE +
+		RT5640_CHPUMP_INT_REG1, 0x0700, 0x0200);
+	regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M2,
+			    RT5640_DEPOP_MASK,
+			    RT5640_DEPOP_MAN);
+	regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M1,
+			    RT5640_HP_CP_MASK |
+			    RT5640_HP_SG_MASK |
+			    RT5640_HP_CB_MASK,
+			    RT5640_HP_CP_PU | RT5640_HP_SG_DIS |
+			    RT5640_HP_CB_PU);
+	regmap_write(rt5640->regmap, RT5640_PR_BASE + RT5640_HP_DCC_INT1,
+			   0x9f00);
+	/* headphone amp power on */
+	regmap_update_bits(rt5640->regmap, RT5640_PWR_ANLG1,
+			    RT5640_PWR_FV1 | RT5640_PWR_FV2, 0);
+	regmap_update_bits(rt5640->regmap, RT5640_PWR_ANLG1,
+			    RT5640_PWR_HA,
+			    RT5640_PWR_HA);
+	usleep_range(20000, 25000);
+	regmap_update_bits(rt5640->regmap, RT5640_PWR_ANLG1,
+			    RT5640_PWR_FV1 | RT5640_PWR_FV2,
+			    RT5640_PWR_FV1 | RT5640_PWR_FV2);
+
+	regmap_update_bits(rt5640->regmap, RT5640_CHARGE_PUMP,
+			    RT5640_PM_HP_MASK, RT5640_PM_HP_HV);
+	regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M1,
+			    RT5640_HP_CO_MASK |
+			    RT5640_HP_SG_MASK,
+			    RT5640_HP_CO_EN | RT5640_HP_SG_EN);
+	regmap_update_bits(rt5640->regmap, RT5640_PR_BASE +
+		RT5640_CHPUMP_INT_REG1, 0x0700, 0x0400);
+}
+
+static void rt5640_pmu_depop(struct snd_soc_codec *codec)
+{
+	struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
+	unsigned int val = 0, pow;
+
+	regmap_read(rt5640->regmap,  RT5640_PWR_ANLG1, &pow);
+	if (rt5640->hp_l_mute || !(pow & RT5640_PWR_HP_L))
+		val |= RT5640_L_MUTE;
+	if (rt5640->hp_r_mute || !(pow & RT5640_PWR_HP_R))
+		val |= RT5640_R_MUTE;
+	/* headphone unmute sequence */
+	regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M3,
+			    RT5640_CP_FQ1_MASK | RT5640_CP_FQ2_MASK |
+			    RT5640_CP_FQ3_MASK,
+			    (RT5640_CP_FQ_192_KHZ << RT5640_CP_FQ1_SFT) |
+			    (RT5640_CP_FQ_12_KHZ << RT5640_CP_FQ2_SFT) |
+			    (RT5640_CP_FQ_192_KHZ << RT5640_CP_FQ3_SFT));
+	regmap_write(rt5640->regmap,
+		RT5640_PR_BASE + RT5640_MAMP_INT_REG2, 0xfc00);
+	regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M1,
+			    RT5640_SMT_TRIG_MASK, RT5640_SMT_TRIG_EN);
+	regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M1,
+			    RT5640_RSTN_MASK, RT5640_RSTN_EN);
+	regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M1,
+			    RT5640_RSTN_MASK | RT5640_HP_L_SMT_MASK |
+			    RT5640_HP_R_SMT_MASK,
+			    RT5640_RSTN_DIS | RT5640_HP_L_SMT_EN |
+			    RT5640_HP_R_SMT_EN);
+	regmap_update_bits(rt5640->regmap, RT5640_HP_VOL,
+			    RT5640_L_MUTE | RT5640_R_MUTE, val);
+	usleep_range(40000, 45000);
+	regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M1,
+			    RT5640_HP_SG_MASK | RT5640_HP_L_SMT_MASK |
+			    RT5640_HP_R_SMT_MASK, RT5640_HP_SG_DIS |
+			    RT5640_HP_L_SMT_DIS | RT5640_HP_R_SMT_DIS);
+
+}
+
+static void rt5640_pmd_depop(struct snd_soc_codec *codec)
+{
+	struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
+	/* headphone mute sequence */
+	regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M3,
+			    RT5640_CP_FQ1_MASK | RT5640_CP_FQ2_MASK |
+			    RT5640_CP_FQ3_MASK,
+			    (RT5640_CP_FQ_96_KHZ << RT5640_CP_FQ1_SFT) |
+			    (RT5640_CP_FQ_12_KHZ << RT5640_CP_FQ2_SFT) |
+			    (RT5640_CP_FQ_96_KHZ << RT5640_CP_FQ3_SFT));
+	regmap_write(rt5640->regmap,
+		RT5640_PR_BASE + RT5640_MAMP_INT_REG2, 0xfc00);
+	regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M1,
+			    RT5640_HP_SG_MASK, RT5640_HP_SG_EN);
+	regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M1,
+			    RT5640_RSTP_MASK, RT5640_RSTP_EN);
+	regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M1,
+			    RT5640_RSTP_MASK | RT5640_HP_L_SMT_MASK |
+			    RT5640_HP_R_SMT_MASK, RT5640_RSTP_DIS |
+			    RT5640_HP_L_SMT_EN | RT5640_HP_R_SMT_EN);
+
+	regmap_update_bits(rt5640->regmap, RT5640_HP_VOL,
+			    RT5640_L_MUTE | RT5640_R_MUTE,
+			    RT5640_L_MUTE | RT5640_R_MUTE);
+	usleep_range(40000, 45000);
+
+	regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M1,
+					    RT5640_HP_SG_MASK |
+					    RT5640_HP_L_SMT_MASK |
+					    RT5640_HP_R_SMT_MASK,
+					    RT5640_HP_SG_DIS |
+					    RT5640_HP_L_SMT_DIS |
+					    RT5640_HP_R_SMT_DIS);
+	regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M1,
+					    RT5640_SMT_TRIG_MASK |
+					    RT5640_HP_CD_PD_MASK |
+					    RT5640_HP_CO_MASK |
+					    RT5640_HP_CP_MASK |
+					    RT5640_HP_SG_MASK |
+					    RT5640_HP_CB_MASK,
+					    RT5640_SMT_TRIG_DIS |
+					    RT5640_HP_CD_PD_EN |
+					    RT5640_HP_CO_DIS | RT5640_HP_CP_PD |
+					    RT5640_HP_SG_EN | RT5640_HP_CB_PD);
+}
+
+static int rt5640_hp_event(struct snd_soc_dapm_widget *w,
+			   struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		rt5640_pmu_depop(codec);
+		break;
+
+	case SND_SOC_DAPM_PRE_PMD:
+		rt5640_pmd_depop(codec);
+		break;
+
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
+static int rt5640_hp_power_event(struct snd_soc_dapm_widget *w,
+			   struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		hp_amp_power_on(codec);
+		break;
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
 static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = {
 	SND_SOC_DAPM_SUPPLY("PLL1", RT5640_PWR_ANLG2,
 			RT5640_PWR_PLL_BIT, 0, NULL, 0),
@@ -1132,15 +1411,23 @@ static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = {
 		rt5640_mono_mix, ARRAY_SIZE(rt5640_mono_mix)),
 	SND_SOC_DAPM_SUPPLY("Improve MONO Amp Drv", RT5640_PWR_ANLG1,
 		RT5640_PWR_MA_BIT, 0, NULL, 0),
-	SND_SOC_DAPM_SUPPLY("Improve HP Amp Drv", RT5640_PWR_ANLG1,
-		SND_SOC_NOPM, 0, NULL, 0),
-	SND_SOC_DAPM_PGA("HP L Amp", RT5640_PWR_ANLG1,
+	SND_SOC_DAPM_SUPPLY_S("Improve HP Amp Drv", 1, SND_SOC_NOPM,
+		0, 0, rt5640_hp_power_event, SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_PGA_S("HP Amp", 1, SND_SOC_NOPM, 0, 0,
+		rt5640_hp_event,
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_SUPPLY("HP L Amp", RT5640_PWR_ANLG1,
 		RT5640_PWR_HP_L_BIT, 0, NULL, 0),
-	SND_SOC_DAPM_PGA("HP R Amp", RT5640_PWR_ANLG1,
+	SND_SOC_DAPM_SUPPLY("HP R Amp", RT5640_PWR_ANLG1,
 		RT5640_PWR_HP_R_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_PGA_E("SPO L Amp", SND_SOC_NOPM,
+		0, 0, NULL, 0, rt5640_spo_l_event,
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+	SND_SOC_DAPM_PGA_E("SPO R Amp", SND_SOC_NOPM,
+		0, 0, NULL, 0, rt5640_spo_r_event,
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
 	SND_SOC_DAPM_SUPPLY("Improve SPK Amp Drv", RT5640_PWR_DIG1,
-		SND_SOC_NOPM, 0, spk_event,
-		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+		RT5640_PWR_CLS_D_BIT, 0, NULL, 0),
 	/* Output Lines */
 	SND_SOC_DAPM_OUTPUT("SPOLP"),
 	SND_SOC_DAPM_OUTPUT("SPOLN"),
@@ -1396,13 +1683,15 @@ static const struct snd_soc_dapm_route rt5640_dapm_routes[] = {
 	{"Mono MIX", "OUTVOL L Switch", "OUTVOL L"},
 	{"Mono MIX", "BST1 Switch", "BST1"},
 
-	{"HP L Amp", NULL, "HPO MIX L"},
-	{"HP R Amp", NULL, "HPO MIX R"},
+	{"HP Amp", NULL, "HPO MIX L"},
+	{"HP Amp", NULL, "HPO MIX R"},
 
-	{"SPOLP", NULL, "SPOL MIX"},
-	{"SPOLN", NULL, "SPOL MIX"},
-	{"SPORP", NULL, "SPOR MIX"},
-	{"SPORN", NULL, "SPOR MIX"},
+	{"SPO L Amp", NULL, "SPOL MIX"},
+	{"SPO R Amp", NULL, "SPOR MIX"},
+	{"SPOLP", NULL, "SPO L Amp"},
+	{"SPOLN", NULL, "SPO L Amp"},
+	{"SPORP", NULL, "SPO R Amp"},
+	{"SPORN", NULL, "SPO R Amp"},
 
 	{"SPOLP", NULL, "Improve SPK Amp Drv"},
 	{"SPOLN", NULL, "Improve SPK Amp Drv"},
@@ -1412,7 +1701,9 @@ static const struct snd_soc_dapm_route rt5640_dapm_routes[] = {
 	{"HPOL", NULL, "Improve HP Amp Drv"},
 	{"HPOR", NULL, "Improve HP Amp Drv"},
 
+	{"HPOL", NULL, "HP Amp"},
 	{"HPOL", NULL, "HP L Amp"},
+	{"HPOR", NULL, "HP Amp"},
 	{"HPOR", NULL, "HP R Amp"},
 	{"LOUTL", NULL, "LOUT MIX"},
 	{"LOUTR", NULL, "LOUT MIX"},
@@ -1792,17 +2083,13 @@ static int rt5640_set_bias_level(struct snd_soc_codec *codec,
 				RT5640_PWR_BG | RT5640_PWR_VREF2,
 				RT5640_PWR_VREF1 | RT5640_PWR_MB |
 				RT5640_PWR_BG | RT5640_PWR_VREF2);
-			mdelay(10);
+			usleep_range(15000, 20000);
 			snd_soc_update_bits(codec, RT5640_PWR_ANLG1,
 				RT5640_PWR_FV1 | RT5640_PWR_FV2,
 				RT5640_PWR_FV1 | RT5640_PWR_FV2);
 			regcache_sync(rt5640->regmap);
 			snd_soc_update_bits(codec, RT5640_DUMMY1,
 						0x0301, 0x0301);
-			snd_soc_update_bits(codec, RT5640_DEPOP_M1,
-						0x001d, 0x0019);
-			snd_soc_update_bits(codec, RT5640_DEPOP_M2,
-						0x2000, 0x2000);
 			snd_soc_update_bits(codec, RT5640_MICBIAS,
 						0x0030, 0x0030);
 		}
@@ -1846,8 +2133,6 @@ static int rt5640_probe(struct snd_soc_codec *codec)
 	rt5640_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
 	snd_soc_update_bits(codec, RT5640_DUMMY1, 0x0301, 0x0301);
-	snd_soc_update_bits(codec, RT5640_DEPOP_M1, 0x001d, 0x0019);
-	snd_soc_update_bits(codec, RT5640_DEPOP_M2, 0x2000, 0x2000);
 	snd_soc_update_bits(codec, RT5640_MICBIAS, 0x0030, 0x0030);
 	snd_soc_update_bits(codec, RT5640_DSP_PATH2, 0xfc00, 0x0c00);
 
diff --git a/sound/soc/codecs/rt5640.h b/sound/soc/codecs/rt5640.h
index c48286d..cb6bce9 100644
--- a/sound/soc/codecs/rt5640.h
+++ b/sound/soc/codecs/rt5640.h
@@ -145,6 +145,8 @@
 
 
 /* Index of Codec Private Register definition */
+#define RT5640_CHPUMP_INT_REG1			0x24
+#define RT5640_MAMP_INT_REG2			0x37
 #define RT5640_3D_SPK				0x63
 #define RT5640_WND_1				0x6c
 #define RT5640_WND_2				0x6d
@@ -153,6 +155,7 @@
 #define RT5640_WND_5				0x70
 #define RT5640_WND_8				0x73
 #define RT5640_DIP_SPK_INF			0x75
+#define RT5640_HP_DCC_INT1			0x77
 #define RT5640_EQ_BW_LOP			0xa0
 #define RT5640_EQ_GN_LOP			0xa1
 #define RT5640_EQ_FC_BP1			0xa2
@@ -1201,6 +1204,14 @@
 #define RT5640_CP_FQ2_SFT			4
 #define RT5640_CP_FQ3_MASK			(0x7)
 #define RT5640_CP_FQ3_SFT			0
+#define RT5640_CP_FQ_1_5_KHZ			0
+#define RT5640_CP_FQ_3_KHZ			1
+#define RT5640_CP_FQ_6_KHZ			2
+#define RT5640_CP_FQ_12_KHZ			3
+#define RT5640_CP_FQ_24_KHZ			4
+#define RT5640_CP_FQ_48_KHZ			5
+#define RT5640_CP_FQ_96_KHZ			6
+#define RT5640_CP_FQ_192_KHZ			7
 
 /* HPOUT charge pump (0x91) */
 #define RT5640_OSW_L_MASK			(0x1 << 11)
@@ -2087,6 +2098,10 @@ struct rt5640_priv {
 	int pll_out;
 
 	int dmic_en;
+	bool spo_l_mute;
+	bool spo_r_mute;
+	bool hp_l_mute;
+	bool hp_r_mute;
 };
 
 #endif
-- 
1.8.1.1.439.g50a6b54

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* Re: [PATCH] ASoC: rt5640: change widget sequence for depop
  2013-08-05  4:19 [PATCH] ASoC: rt5640: change widget sequence for depop bardliao
@ 2013-08-05 14:48 ` Mark Brown
  2013-08-05 17:21   ` Lars-Peter Clausen
  2013-08-05 17:17 ` [PATCH] ASoC: rt5640: change widget sequence for depop Stephen Warren
  2013-08-05 17:19 ` Lars-Peter Clausen
  2 siblings, 1 reply; 35+ messages in thread
From: Mark Brown @ 2013-08-05 14:48 UTC (permalink / raw)
  To: bardliao; +Cc: oder_chiou, alsa-devel, swarren, swarren, lgirdwood, flove


[-- Attachment #1.1: Type: text/plain, Size: 473 bytes --]

On Mon, Aug 05, 2013 at 12:19:03PM +0800, bardliao@realtek.com wrote:
> From: Bard Liao <bardliao@realtek.com>
> 
> Add mute/unmute control in widget event and modify the power on/off sequence to avoid pop noise.

This looks like you should be using Lars-Peter's patch for controls that
are disabled while a widget isn't powered - as far as I can tell from a
quick read through all this does is keep the speaker/headphone muted
while the outputs are powered down.

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] ASoC: rt5640: change widget sequence for depop
  2013-08-05  4:19 [PATCH] ASoC: rt5640: change widget sequence for depop bardliao
  2013-08-05 14:48 ` Mark Brown
@ 2013-08-05 17:17 ` Stephen Warren
  2013-08-05 17:19 ` Lars-Peter Clausen
  2 siblings, 0 replies; 35+ messages in thread
From: Stephen Warren @ 2013-08-05 17:17 UTC (permalink / raw)
  To: bardliao; +Cc: oder_chiou, alsa-devel, swarren, lgirdwood, broonie, flove

On 08/04/2013 10:19 PM, bardliao@realtek.com wrote:
> From: Bard Liao <bardliao@realtek.com>
> 
> Add mute/unmute control in widget event and modify the power on/off sequence to avoid pop noise.

FWIW, this version,
Tested-by: Stephen Warren <swarren@nvidia.com>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] ASoC: rt5640: change widget sequence for depop
  2013-08-05  4:19 [PATCH] ASoC: rt5640: change widget sequence for depop bardliao
  2013-08-05 14:48 ` Mark Brown
  2013-08-05 17:17 ` [PATCH] ASoC: rt5640: change widget sequence for depop Stephen Warren
@ 2013-08-05 17:19 ` Lars-Peter Clausen
  2 siblings, 0 replies; 35+ messages in thread
From: Lars-Peter Clausen @ 2013-08-05 17:19 UTC (permalink / raw)
  To: bardliao
  Cc: oder_chiou, alsa-devel, swarren, swarren, lgirdwood, broonie, flove

On 08/05/2013 06:19 AM, bardliao@realtek.com wrote:
> From: Bard Liao <bardliao@realtek.com>
> 
> Add mute/unmute control in widget event and modify the power on/off sequence to avoid pop noise.
> 
> Signed-off-by: Bard Liao <bardliao@realtek.com>
> ---
> Please ignore the previous patch.
> I have tested speaker and headphone playback on this patch.
> ---
>  sound/soc/codecs/rt5640.c | 389 +++++++++++++++++++++++++++++++++++++++-------
>  sound/soc/codecs/rt5640.h |  15 ++
>  2 files changed, 352 insertions(+), 52 deletions(-)
> 
> diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
> index 4db7314..cae3f46 100644
> --- a/sound/soc/codecs/rt5640.c
> +++ b/sound/soc/codecs/rt5640.c
> @@ -50,8 +50,6 @@ static const struct regmap_range_cfg rt5640_ranges[] = {
>  
>  static struct reg_default init_list[] = {
>  	{RT5640_PR_BASE + 0x3d,	0x3600},
> -	{RT5640_PR_BASE + 0x1c,	0x0D21},
> -	{RT5640_PR_BASE + 0x1b,	0x0000},
>  	{RT5640_PR_BASE + 0x12,	0x0aa8},
>  	{RT5640_PR_BASE + 0x14,	0x0aaa},
>  	{RT5640_PR_BASE + 0x20,	0x6110},
> @@ -378,21 +376,119 @@ static const SOC_ENUM_SINGLE_DECL(rt5640_if2_adc_enum, RT5640_DIG_INF_DATA,
>  static const char * const rt5640_clsd_spk_ratio[] = {"1.66x", "1.83x", "1.94x",
>  	"2x", "2.11x", "2.22x", "2.33x", "2.44x", "2.55x", "2.66x", "2.77x"};
>  
> +static const char * const rt5640_mute_mode[] = {"mute", "unmute"};
> +
> +static const SOC_ENUM_SINGLE_DECL(rt5640_hp_enum, 0, 0, rt5640_mute_mode);
> +static const SOC_ENUM_SINGLE_DECL(rt5640_spo_enum, 0, 0, rt5640_mute_mode);
> +

These enums seem to be unused. (And switches should be used for mutes and enums)

- Lars

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] ASoC: rt5640: change widget sequence for depop
  2013-08-05 14:48 ` Mark Brown
@ 2013-08-05 17:21   ` Lars-Peter Clausen
  2013-08-05 17:58     ` Mark Brown
  2013-08-06  8:07     ` [PATCH] ASoC: rt5640: change widget sequencefordepop Bard Liao
  0 siblings, 2 replies; 35+ messages in thread
From: Lars-Peter Clausen @ 2013-08-05 17:21 UTC (permalink / raw)
  To: Mark Brown
  Cc: oder_chiou, alsa-devel, swarren, swarren, lgirdwood, bardliao, flove

On 08/05/2013 04:48 PM, Mark Brown wrote:
> On Mon, Aug 05, 2013 at 12:19:03PM +0800, bardliao@realtek.com wrote:
>> From: Bard Liao <bardliao@realtek.com>
>>
>> Add mute/unmute control in widget event and modify the power on/off sequence to avoid pop noise.
> 
> This looks like you should be using Lars-Peter's patch for controls that
> are disabled while a widget isn't powered - as far as I can tell from a
> quick read through all this does is keep the speaker/headphone muted
> while the outputs are powered down.

The driver is using stereo controls though. So either support for stereo
controls needs to be added to DAPM (which shouldn't be too hard) or the
control needs to be split into two mono controls.

- Lars

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] ASoC: rt5640: change widget sequence for depop
  2013-08-05 17:21   ` Lars-Peter Clausen
@ 2013-08-05 17:58     ` Mark Brown
  2013-08-06  8:07     ` [PATCH] ASoC: rt5640: change widget sequencefordepop Bard Liao
  1 sibling, 0 replies; 35+ messages in thread
From: Mark Brown @ 2013-08-05 17:58 UTC (permalink / raw)
  To: Lars-Peter Clausen
  Cc: oder_chiou, alsa-devel, swarren, swarren, lgirdwood, bardliao, flove


[-- Attachment #1.1: Type: text/plain, Size: 693 bytes --]

On Mon, Aug 05, 2013 at 07:21:21PM +0200, Lars-Peter Clausen wrote:
> On 08/05/2013 04:48 PM, Mark Brown wrote:

> > This looks like you should be using Lars-Peter's patch for controls that
> > are disabled while a widget isn't powered - as far as I can tell from a
> > quick read through all this does is keep the speaker/headphone muted
> > while the outputs are powered down.

> The driver is using stereo controls though. So either support for stereo
> controls needs to be added to DAPM (which shouldn't be too hard) or the
> control needs to be split into two mono controls.

Yes, I think we should get the stereo support done - this sort of thing
is the main use case I can see for it.

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] ASoC: rt5640: change widget sequencefordepop
  2013-08-05 17:21   ` Lars-Peter Clausen
  2013-08-05 17:58     ` Mark Brown
@ 2013-08-06  8:07     ` Bard Liao
  2013-08-06  8:45       ` Lars-Peter Clausen
  1 sibling, 1 reply; 35+ messages in thread
From: Bard Liao @ 2013-08-06  8:07 UTC (permalink / raw)
  To: Lars-Peter Clausen, Mark Brown
  Cc: Oder Chiou, alsa-devel, swarren, swarren, lgirdwood, Flove

> -----Original Message-----
> From: Lars-Peter Clausen [mailto:lars@metafoo.de]
> Sent: Tuesday, August 06, 2013 1:21 AM
> To: Mark Brown
> Cc: Bard Liao; Oder Chiou; alsa-devel@alsa-project.org; swarren@nvidia.com;
> swarren@wwwdotorg.org; lgirdwood@gmail.com; Flove
> Subject: Re: [alsa-devel] [PATCH] ASoC: rt5640: change widget sequence
> fordepop
> 
> On 08/05/2013 04:48 PM, Mark Brown wrote:
> > On Mon, Aug 05, 2013 at 12:19:03PM +0800, bardliao@realtek.com wrote:
> >> From: Bard Liao <bardliao@realtek.com>
> >>
> >> Add mute/unmute control in widget event and modify the power on/off
> sequence to avoid pop noise.
> >
> > This looks like you should be using Lars-Peter's patch for controls
> > that are disabled while a widget isn't powered - as far as I can tell
> > from a quick read through all this does is keep the speaker/headphone
> > muted while the outputs are powered down.
> 
> The driver is using stereo controls though. So either support for stereo controls
> needs to be added to DAPM (which shouldn't be too hard) or the control needs
> to be split into two mono controls.
> 
> - Lars

I think I need to use SND_SOC_DAPM_SWITCH with SOC_DAPM_SINGLE_AUTODISABLE for this control.
Am I right?
I am trying to do that, but meet a problem.
If I set speaker switch unmute before playing music, dapm will mute it automatically in power on sequence.
The only way I can unmute speaker is set speaker switch unmute while playing music.
Did I miss something?

> 
> 
> ------Please consider the environment before printing this e-mail.

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] ASoC: rt5640: change widget sequencefordepop
  2013-08-06  8:07     ` [PATCH] ASoC: rt5640: change widget sequencefordepop Bard Liao
@ 2013-08-06  8:45       ` Lars-Peter Clausen
  2013-08-06  9:13         ` [PATCH] ASoC: rt5640: change widgetsequencefordepop Bard Liao
  0 siblings, 1 reply; 35+ messages in thread
From: Lars-Peter Clausen @ 2013-08-06  8:45 UTC (permalink / raw)
  To: Bard Liao
  Cc: Oder Chiou, alsa-devel, swarren, swarren, lgirdwood, Mark Brown, Flove

On 08/06/2013 10:07 AM, Bard Liao wrote:
>> -----Original Message-----
>> From: Lars-Peter Clausen [mailto:lars@metafoo.de]
>> Sent: Tuesday, August 06, 2013 1:21 AM
>> To: Mark Brown
>> Cc: Bard Liao; Oder Chiou; alsa-devel@alsa-project.org; swarren@nvidia.com;
>> swarren@wwwdotorg.org; lgirdwood@gmail.com; Flove
>> Subject: Re: [alsa-devel] [PATCH] ASoC: rt5640: change widget sequence
>> fordepop
>>
>> On 08/05/2013 04:48 PM, Mark Brown wrote:
>>> On Mon, Aug 05, 2013 at 12:19:03PM +0800, bardliao@realtek.com wrote:
>>>> From: Bard Liao <bardliao@realtek.com>
>>>>
>>>> Add mute/unmute control in widget event and modify the power on/off
>> sequence to avoid pop noise.
>>>
>>> This looks like you should be using Lars-Peter's patch for controls
>>> that are disabled while a widget isn't powered - as far as I can tell
>>> from a quick read through all this does is keep the speaker/headphone
>>> muted while the outputs are powered down.
>>
>> The driver is using stereo controls though. So either support for stereo controls
>> needs to be added to DAPM (which shouldn't be too hard) or the control needs
>> to be split into two mono controls.
>>
>> - Lars
>
> I think I need to use SND_SOC_DAPM_SWITCH with SOC_DAPM_SINGLE_AUTODISABLE for this control.
> Am I right?
> I am trying to do that, but meet a problem.
> If I set speaker switch unmute before playing music, dapm will mute it automatically in power on sequence.
> The only way I can unmute speaker is set speaker switch unmute while playing music.

DAPM should unmute the switch on power up and mute it on power down. The 
Speaker Channel Switch control has the invert flag set did you also set the 
invert flag for the new autodisable control?

- Lars

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] ASoC: rt5640: change widgetsequencefordepop
  2013-08-06  8:45       ` Lars-Peter Clausen
@ 2013-08-06  9:13         ` Bard Liao
  2013-08-06  9:35           ` Lars-Peter Clausen
  0 siblings, 1 reply; 35+ messages in thread
From: Bard Liao @ 2013-08-06  9:13 UTC (permalink / raw)
  To: Lars-Peter Clausen
  Cc: Oder Chiou, alsa-devel, swarren, swarren, lgirdwood, Mark Brown, Flove

> > I think I need to use SND_SOC_DAPM_SWITCH with
> SOC_DAPM_SINGLE_AUTODISABLE for this control.
> > Am I right?
> > I am trying to do that, but meet a problem.
> > If I set speaker switch unmute before playing music, dapm will mute it
> automatically in power on sequence.
> > The only way I can unmute speaker is set speaker switch unmute while
> playing music.
> 
> DAPM should unmute the switch on power up and mute it on power down. The
> Speaker Channel Switch control has the invert flag set did you also set the
> invert flag for the new autodisable control?

Yes, the related code is as below.
static const struct snd_kcontrol_new spk_l_enable_control =
	SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5640_SPK_VOL,
		RT5640_L_MUTE_SFT, 1, 1);

static const struct snd_kcontrol_new spk_r_enable_control =
	SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5640_SPK_VOL,
		RT5640_R_MUTE_SFT, 1, 1);

	SND_SOC_DAPM_SWITCH("Speaker L Playback", SND_SOC_NOPM, 0, 0,
			&spk_l_enable_control),
	SND_SOC_DAPM_SWITCH("Speaker R Playback", SND_SOC_NOPM, 0, 0,
			&spk_r_enable_control),

I tried set SND_SOC_DAPM_SWITCH invert flag, but it comes the same result.
I will do some more experiments about it.

> 
> - Lars
> 
> 
> ------Please consider the environment before printing this e-mail.

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] ASoC: rt5640: change widgetsequencefordepop
  2013-08-06  9:13         ` [PATCH] ASoC: rt5640: change widgetsequencefordepop Bard Liao
@ 2013-08-06  9:35           ` Lars-Peter Clausen
  2013-08-06 10:07             ` Bard Liao
  0 siblings, 1 reply; 35+ messages in thread
From: Lars-Peter Clausen @ 2013-08-06  9:35 UTC (permalink / raw)
  To: Bard Liao
  Cc: Oder Chiou, alsa-devel, swarren, swarren, lgirdwood, Mark Brown, Flove

On 08/06/2013 11:13 AM, Bard Liao wrote:
>>> I think I need to use SND_SOC_DAPM_SWITCH with
>> SOC_DAPM_SINGLE_AUTODISABLE for this control.
>>> Am I right?
>>> I am trying to do that, but meet a problem.
>>> If I set speaker switch unmute before playing music, dapm will mute it
>> automatically in power on sequence.
>>> The only way I can unmute speaker is set speaker switch unmute while
>> playing music.
>>
>> DAPM should unmute the switch on power up and mute it on power down. The
>> Speaker Channel Switch control has the invert flag set did you also set the
>> invert flag for the new autodisable control?
>
> Yes, the related code is as below.
> static const struct snd_kcontrol_new spk_l_enable_control =
> 	SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5640_SPK_VOL,
> 		RT5640_L_MUTE_SFT, 1, 1);
>
> static const struct snd_kcontrol_new spk_r_enable_control =
> 	SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5640_SPK_VOL,
> 		RT5640_R_MUTE_SFT, 1, 1);
>
> 	SND_SOC_DAPM_SWITCH("Speaker L Playback", SND_SOC_NOPM, 0, 0,
> 			&spk_l_enable_control),
> 	SND_SOC_DAPM_SWITCH("Speaker R Playback", SND_SOC_NOPM, 0, 0,
> 			&spk_r_enable_control),

Looks good. Maybe I got the invert = 1 case wrong somewhere. Can you add a 
couple of printks and send me the result?

diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 2da258b..18c62ae 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -229,6 +229,9 @@
  			template.id = snd_soc_dapm_kcontrol;
  			template.name = kcontrol->id.name;

+			printk("new control: %s %d\n", template->name,
+				template->off_val);
+
  			data->widget = snd_soc_dapm_new_control(widget->dapm,
  				&template);
  			if (!data->widget) {
@@ -337,8 +340,10 @@
  	if (data->value == value)
  		return false;

-	if (data->widget)
+	if (data->widget) {
  		data->widget->on_val = value;
+		printk("%s->on_val = %d\n", data->widget->name, value);
+	}

  	data->value = value;

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* Re: [PATCH] ASoC: rt5640: change widgetsequencefordepop
  2013-08-06  9:35           ` Lars-Peter Clausen
@ 2013-08-06 10:07             ` Bard Liao
  2013-08-06 10:16               ` Lars-Peter Clausen
  0 siblings, 1 reply; 35+ messages in thread
From: Bard Liao @ 2013-08-06 10:07 UTC (permalink / raw)
  To: Lars-Peter Clausen
  Cc: Oder Chiou, alsa-devel, swarren, swarren, lgirdwood, Mark Brown, Flove

> -----Original Message-----
> From: Lars-Peter Clausen [mailto:lars@metafoo.de]
> Sent: Tuesday, August 06, 2013 5:36 PM
> To: Bard Liao
> Cc: Mark Brown; Oder Chiou; alsa-devel@alsa-project.org;
> swarren@nvidia.com; swarren@wwwdotorg.org; lgirdwood@gmail.com; Flove
> Subject: Re: [alsa-devel] [PATCH] ASoC: rt5640: change
> widgetsequencefordepop
> 
> On 08/06/2013 11:13 AM, Bard Liao wrote:
> >>> I think I need to use SND_SOC_DAPM_SWITCH with
> >> SOC_DAPM_SINGLE_AUTODISABLE for this control.
> >>> Am I right?
> >>> I am trying to do that, but meet a problem.
> >>> If I set speaker switch unmute before playing music, dapm will mute
> >>> it
> >> automatically in power on sequence.
> >>> The only way I can unmute speaker is set speaker switch unmute while
> >> playing music.
> >>
> >> DAPM should unmute the switch on power up and mute it on power down.
> >> The Speaker Channel Switch control has the invert flag set did you
> >> also set the invert flag for the new autodisable control?
> >
> > Yes, the related code is as below.
> > static const struct snd_kcontrol_new spk_l_enable_control =
> > 	SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5640_SPK_VOL,
> > 		RT5640_L_MUTE_SFT, 1, 1);
> >
> > static const struct snd_kcontrol_new spk_r_enable_control =
> > 	SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5640_SPK_VOL,
> > 		RT5640_R_MUTE_SFT, 1, 1);
> >
> > 	SND_SOC_DAPM_SWITCH("Speaker L Playback", SND_SOC_NOPM, 0, 0,
> > 			&spk_l_enable_control),
> > 	SND_SOC_DAPM_SWITCH("Speaker R Playback", SND_SOC_NOPM, 0, 0,
> > 			&spk_r_enable_control),
> 
> Looks good. Maybe I got the invert = 1 case wrong somewhere. Can you add a
> couple of printks and send me the result?

The result is as below.

[    9.418738] new control: Speaker R Playback Switch 1
[    9.423949] new control: Speaker L Playback Switch 1

root@tegra-ubuntu:/home/ubuntu# amixer cset name="Speaker L Playback Switch" 0
numid=25,iface=MIXER,name='Speaker L Playback Switch'
  ; type=BOOLEAN,access=rw------,values=1
  : values=off
root@tegra-ubuntu:/home/ubuntu# dmesg -c
[  163.717158] Speaker L Playback Switch->on_val = 1
root@tegra-ubuntu:/home/ubuntu#
root@tegra-ubuntu:/home/ubuntu# amixer cset name="Speaker L Playback Switch" 1
numid=25,iface=MIXER,name='Speaker L Playback Switch'
  ; type=BOOLEAN,access=rw------,values=1
  : values=on
root@tegra-ubuntu:/home/ubuntu#
root@tegra-ubuntu:/home/ubuntu# dmesg -c
[  174.482833] Speaker L Playback Switch->on_val = 0

> 
> diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index
> 2da258b..18c62ae 100644
> --- a/sound/soc/soc-dapm.c
> +++ b/sound/soc/soc-dapm.c
> @@ -229,6 +229,9 @@
>   			template.id = snd_soc_dapm_kcontrol;
>   			template.name = kcontrol->id.name;
> 
> +			printk("new control: %s %d\n", template->name,
> +				template->off_val);
> +
>   			data->widget = snd_soc_dapm_new_control(widget->dapm,
>   				&template);
>   			if (!data->widget) {
> @@ -337,8 +340,10 @@
>   	if (data->value == value)
>   		return false;
> 
> -	if (data->widget)
> +	if (data->widget) {
>   		data->widget->on_val = value;
> +		printk("%s->on_val = %d\n", data->widget->name, value);
> +	}
> 
>   	data->value = value;
> 
> 
> ------Please consider the environment before printing this e-mail.

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] ASoC: rt5640: change widgetsequencefordepop
  2013-08-06 10:07             ` Bard Liao
@ 2013-08-06 10:16               ` Lars-Peter Clausen
  2013-08-06 11:04                 ` Bard Liao
  0 siblings, 1 reply; 35+ messages in thread
From: Lars-Peter Clausen @ 2013-08-06 10:16 UTC (permalink / raw)
  To: Bard Liao
  Cc: Oder Chiou, alsa-devel, swarren, swarren, lgirdwood, Mark Brown, Flove

On 08/06/2013 12:07 PM, Bard Liao wrote:
>> -----Original Message-----
>> From: Lars-Peter Clausen [mailto:lars@metafoo.de]
>> Sent: Tuesday, August 06, 2013 5:36 PM
>> To: Bard Liao
>> Cc: Mark Brown; Oder Chiou; alsa-devel@alsa-project.org;
>> swarren@nvidia.com; swarren@wwwdotorg.org; lgirdwood@gmail.com; Flove
>> Subject: Re: [alsa-devel] [PATCH] ASoC: rt5640: change
>> widgetsequencefordepop
>>
>> On 08/06/2013 11:13 AM, Bard Liao wrote:
>>>>> I think I need to use SND_SOC_DAPM_SWITCH with
>>>> SOC_DAPM_SINGLE_AUTODISABLE for this control.
>>>>> Am I right?
>>>>> I am trying to do that, but meet a problem.
>>>>> If I set speaker switch unmute before playing music, dapm will mute
>>>>> it
>>>> automatically in power on sequence.
>>>>> The only way I can unmute speaker is set speaker switch unmute while
>>>> playing music.
>>>>
>>>> DAPM should unmute the switch on power up and mute it on power down.
>>>> The Speaker Channel Switch control has the invert flag set did you
>>>> also set the invert flag for the new autodisable control?
>>>
>>> Yes, the related code is as below.
>>> static const struct snd_kcontrol_new spk_l_enable_control =
>>> 	SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5640_SPK_VOL,
>>> 		RT5640_L_MUTE_SFT, 1, 1);
>>>
>>> static const struct snd_kcontrol_new spk_r_enable_control =
>>> 	SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5640_SPK_VOL,
>>> 		RT5640_R_MUTE_SFT, 1, 1);
>>>
>>> 	SND_SOC_DAPM_SWITCH("Speaker L Playback", SND_SOC_NOPM, 0, 0,
>>> 			&spk_l_enable_control),
>>> 	SND_SOC_DAPM_SWITCH("Speaker R Playback", SND_SOC_NOPM, 0, 0,
>>> 			&spk_r_enable_control),
>>
>> Looks good. Maybe I got the invert = 1 case wrong somewhere. Can you add a
>> couple of printks and send me the result?
>
> The result is as below.
>
> [    9.418738] new control: Speaker R Playback Switch 1
> [    9.423949] new control: Speaker L Playback Switch 1
>
> root@tegra-ubuntu:/home/ubuntu# amixer cset name="Speaker L Playback Switch" 0
> numid=25,iface=MIXER,name='Speaker L Playback Switch'
>    ; type=BOOLEAN,access=rw------,values=1
>    : values=off
> root@tegra-ubuntu:/home/ubuntu# dmesg -c
> [  163.717158] Speaker L Playback Switch->on_val = 1
> root@tegra-ubuntu:/home/ubuntu#
> root@tegra-ubuntu:/home/ubuntu# amixer cset name="Speaker L Playback Switch" 1
> numid=25,iface=MIXER,name='Speaker L Playback Switch'
>    ; type=BOOLEAN,access=rw------,values=1
>    : values=on
> root@tegra-ubuntu:/home/ubuntu#
> root@tegra-ubuntu:/home/ubuntu# dmesg -c
> [  174.482833] Speaker L Playback Switch->on_val = 0

That looks right, right? on_val is what is going to be written to the control's 
register. And in your case this needs to be 0 for unmute and 1 for mute. So why 
would DAPM mute the control on power-up?

- Lars

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] ASoC: rt5640: change widgetsequencefordepop
  2013-08-06 10:16               ` Lars-Peter Clausen
@ 2013-08-06 11:04                 ` Bard Liao
  2013-08-06 11:31                   ` Lars-Peter Clausen
  0 siblings, 1 reply; 35+ messages in thread
From: Bard Liao @ 2013-08-06 11:04 UTC (permalink / raw)
  To: Lars-Peter Clausen
  Cc: Oder Chiou, alsa-devel, swarren, swarren, lgirdwood, Mark Brown, Flove

> -----Original Message-----
> From: Lars-Peter Clausen [mailto:lars@metafoo.de]
> Sent: Tuesday, August 06, 2013 6:17 PM
> To: Bard Liao
> Cc: Mark Brown; Oder Chiou; alsa-devel@alsa-project.org;
> swarren@nvidia.com; swarren@wwwdotorg.org; lgirdwood@gmail.com; Flove
> Subject: Re: [alsa-devel] [PATCH] ASoC: rt5640: change
> widgetsequencefordepop
> 
> On 08/06/2013 12:07 PM, Bard Liao wrote:
> >> -----Original Message-----
> >> From: Lars-Peter Clausen [mailto:lars@metafoo.de]
> >> Sent: Tuesday, August 06, 2013 5:36 PM
> >> To: Bard Liao
> >> Cc: Mark Brown; Oder Chiou; alsa-devel@alsa-project.org;
> >> swarren@nvidia.com; swarren@wwwdotorg.org; lgirdwood@gmail.com;
> Flove
> >> Subject: Re: [alsa-devel] [PATCH] ASoC: rt5640: change
> >> widgetsequencefordepop
> >>
> >> On 08/06/2013 11:13 AM, Bard Liao wrote:
> >>>>> I think I need to use SND_SOC_DAPM_SWITCH with
> >>>> SOC_DAPM_SINGLE_AUTODISABLE for this control.
> >>>>> Am I right?
> >>>>> I am trying to do that, but meet a problem.
> >>>>> If I set speaker switch unmute before playing music, dapm will
> >>>>> mute it
> >>>> automatically in power on sequence.
> >>>>> The only way I can unmute speaker is set speaker switch unmute
> >>>>> while
> >>>> playing music.
> >>>>
> >>>> DAPM should unmute the switch on power up and mute it on power
> down.
> >>>> The Speaker Channel Switch control has the invert flag set did you
> >>>> also set the invert flag for the new autodisable control?
> >>>
> >>> Yes, the related code is as below.
> >>> static const struct snd_kcontrol_new spk_l_enable_control =
> >>> 	SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5640_SPK_VOL,
> >>> 		RT5640_L_MUTE_SFT, 1, 1);
> >>>
> >>> static const struct snd_kcontrol_new spk_r_enable_control =
> >>> 	SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5640_SPK_VOL,
> >>> 		RT5640_R_MUTE_SFT, 1, 1);
> >>>
> >>> 	SND_SOC_DAPM_SWITCH("Speaker L Playback", SND_SOC_NOPM, 0,
> 0,
> >>> 			&spk_l_enable_control),
> >>> 	SND_SOC_DAPM_SWITCH("Speaker R Playback", SND_SOC_NOPM,
> 0, 0,
> >>> 			&spk_r_enable_control),
> >>
> >> Looks good. Maybe I got the invert = 1 case wrong somewhere. Can you
> >> add a couple of printks and send me the result?
> >
> > The result is as below.
> >
> > [    9.418738] new control: Speaker R Playback Switch 1
> > [    9.423949] new control: Speaker L Playback Switch 1
> >
> > root@tegra-ubuntu:/home/ubuntu# amixer cset name="Speaker L Playback
> > Switch" 0 numid=25,iface=MIXER,name='Speaker L Playback Switch'
> >    ; type=BOOLEAN,access=rw------,values=1
> >    : values=off
> > root@tegra-ubuntu:/home/ubuntu# dmesg -c [  163.717158] Speaker L
> > Playback Switch->on_val = 1 root@tegra-ubuntu:/home/ubuntu#
> > root@tegra-ubuntu:/home/ubuntu# amixer cset name="Speaker L Playback
> > Switch" 1 numid=25,iface=MIXER,name='Speaker L Playback Switch'
> >    ; type=BOOLEAN,access=rw------,values=1
> >    : values=on
> > root@tegra-ubuntu:/home/ubuntu#
> > root@tegra-ubuntu:/home/ubuntu# dmesg -c [  174.482833] Speaker L
> > Playback Switch->on_val = 0
> 
> That looks right, right? on_val is what is going to be written to the control's
> register. And in your case this needs to be 0 for unmute and 1 for mute. So why
> would DAPM mute the control on power-up?

I think the issue is that the on_val is set to be off_val in dapm_kcontrol_data_alloc.
And if I launch "amixer cget name="Speaker L Playback Switch" after the system boot up immediately it will show values=on.
I think it should show values=off, since the dapm path is actually disconnected.
If I launch " amixer cset name="Speaker L Playback Switch" 1", the dapm path will be connected.
But dapm_kcontrol_set_value will return false in if (data->value == value) condition.
So the on_val will not be set in dapm_kcontrol_set_value, and will equal to off_val still.
If I set "Speaker L Playback Switch" off and on, the issue will disappear.

> 
> - Lars
> 
> 
> ------Please consider the environment before printing this e-mail.

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] ASoC: rt5640: change widgetsequencefordepop
  2013-08-06 11:04                 ` Bard Liao
@ 2013-08-06 11:31                   ` Lars-Peter Clausen
  2013-08-07  1:32                     ` Bard Liao
  2013-08-07  5:40                     ` Bard Liao
  0 siblings, 2 replies; 35+ messages in thread
From: Lars-Peter Clausen @ 2013-08-06 11:31 UTC (permalink / raw)
  To: Bard Liao
  Cc: Oder Chiou, alsa-devel, swarren, swarren, lgirdwood, Mark Brown, Flove

On 08/06/2013 01:04 PM, Bard Liao wrote:
>> -----Original Message-----
>> From: Lars-Peter Clausen [mailto:lars@metafoo.de]
>> Sent: Tuesday, August 06, 2013 6:17 PM
>> To: Bard Liao
>> Cc: Mark Brown; Oder Chiou; alsa-devel@alsa-project.org;
>> swarren@nvidia.com; swarren@wwwdotorg.org; lgirdwood@gmail.com; Flove
>> Subject: Re: [alsa-devel] [PATCH] ASoC: rt5640: change
>> widgetsequencefordepop
>>
>> On 08/06/2013 12:07 PM, Bard Liao wrote:
>>>> -----Original Message-----
>>>> From: Lars-Peter Clausen [mailto:lars@metafoo.de]
>>>> Sent: Tuesday, August 06, 2013 5:36 PM
>>>> To: Bard Liao
>>>> Cc: Mark Brown; Oder Chiou; alsa-devel@alsa-project.org;
>>>> swarren@nvidia.com; swarren@wwwdotorg.org; lgirdwood@gmail.com;
>> Flove
>>>> Subject: Re: [alsa-devel] [PATCH] ASoC: rt5640: change
>>>> widgetsequencefordepop
>>>>
>>>> On 08/06/2013 11:13 AM, Bard Liao wrote:
>>>>>>> I think I need to use SND_SOC_DAPM_SWITCH with
>>>>>> SOC_DAPM_SINGLE_AUTODISABLE for this control.
>>>>>>> Am I right?
>>>>>>> I am trying to do that, but meet a problem.
>>>>>>> If I set speaker switch unmute before playing music, dapm will
>>>>>>> mute it
>>>>>> automatically in power on sequence.
>>>>>>> The only way I can unmute speaker is set speaker switch unmute
>>>>>>> while
>>>>>> playing music.
>>>>>>
>>>>>> DAPM should unmute the switch on power up and mute it on power
>> down.
>>>>>> The Speaker Channel Switch control has the invert flag set did you
>>>>>> also set the invert flag for the new autodisable control?
>>>>>
>>>>> Yes, the related code is as below.
>>>>> static const struct snd_kcontrol_new spk_l_enable_control =
>>>>> 	SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5640_SPK_VOL,
>>>>> 		RT5640_L_MUTE_SFT, 1, 1);
>>>>>
>>>>> static const struct snd_kcontrol_new spk_r_enable_control =
>>>>> 	SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5640_SPK_VOL,
>>>>> 		RT5640_R_MUTE_SFT, 1, 1);
>>>>>
>>>>> 	SND_SOC_DAPM_SWITCH("Speaker L Playback", SND_SOC_NOPM, 0,
>> 0,
>>>>> 			&spk_l_enable_control),
>>>>> 	SND_SOC_DAPM_SWITCH("Speaker R Playback", SND_SOC_NOPM,
>> 0, 0,
>>>>> 			&spk_r_enable_control),
>>>>
>>>> Looks good. Maybe I got the invert = 1 case wrong somewhere. Can you
>>>> add a couple of printks and send me the result?
>>>
>>> The result is as below.
>>>
>>> [    9.418738] new control: Speaker R Playback Switch 1
>>> [    9.423949] new control: Speaker L Playback Switch 1
>>>
>>> root@tegra-ubuntu:/home/ubuntu# amixer cset name="Speaker L Playback
>>> Switch" 0 numid=25,iface=MIXER,name='Speaker L Playback Switch'
>>>     ; type=BOOLEAN,access=rw------,values=1
>>>     : values=off
>>> root@tegra-ubuntu:/home/ubuntu# dmesg -c [  163.717158] Speaker L
>>> Playback Switch->on_val = 1 root@tegra-ubuntu:/home/ubuntu#
>>> root@tegra-ubuntu:/home/ubuntu# amixer cset name="Speaker L Playback
>>> Switch" 1 numid=25,iface=MIXER,name='Speaker L Playback Switch'
>>>     ; type=BOOLEAN,access=rw------,values=1
>>>     : values=on
>>> root@tegra-ubuntu:/home/ubuntu#
>>> root@tegra-ubuntu:/home/ubuntu# dmesg -c [  174.482833] Speaker L
>>> Playback Switch->on_val = 0
>>
>> That looks right, right? on_val is what is going to be written to the control's
>> register. And in your case this needs to be 0 for unmute and 1 for mute. So why
>> would DAPM mute the control on power-up?
>
> I think the issue is that the on_val is set to be off_val in dapm_kcontrol_data_alloc.
> And if I launch "amixer cget name="Speaker L Playback Switch" after the system boot up immediately it will show values=on.
> I think it should show values=off, since the dapm path is actually disconnected.
> If I launch " amixer cset name="Speaker L Playback Switch" 1", the dapm path will be connected.
> But dapm_kcontrol_set_value will return false in if (data->value == value) condition.
> So the on_val will not be set in dapm_kcontrol_set_value, and will equal to off_val still.
> If I set "Speaker L Playback Switch" off and on, the issue will disappear.

Makes sense. So this should fix it, I guess:

--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -229,6 +229,8 @@ static int dapm_kcontrol_data_alloc(struct
  			template.id = snd_soc_dapm_kcontrol;
  			template.name = kcontrol->id.name;

+			data->value = template.on_val;
+
  			data->widget = snd_soc_dapm_new_control(widget->dapm,
  				&template);
  			if (!data->widget) {

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] ASoC: rt5640: change widgetsequencefordepop
  2013-08-06 11:31                   ` Lars-Peter Clausen
@ 2013-08-07  1:32                     ` Bard Liao
  2013-08-07  5:40                     ` Bard Liao
  1 sibling, 0 replies; 35+ messages in thread
From: Bard Liao @ 2013-08-07  1:32 UTC (permalink / raw)
  To: Lars-Peter Clausen
  Cc: Oder Chiou, alsa-devel, swarren, swarren, lgirdwood, Mark Brown, Flove

> Makes sense. So this should fix it, I guess:
> 
> --- a/sound/soc/soc-dapm.c
> +++ b/sound/soc/soc-dapm.c
> @@ -229,6 +229,8 @@ static int dapm_kcontrol_data_alloc(struct
>   			template.id = snd_soc_dapm_kcontrol;
>   			template.name = kcontrol->id.name;
> 
> +			data->value = template.on_val;
> +
>   			data->widget = snd_soc_dapm_new_control(widget->dapm,
>   				&template);
>   			if (!data->widget) {
> 

It works. Thanks.

> 
> 
> ------Please consider the environment before printing this e-mail.

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] ASoC: rt5640: change widgetsequencefordepop
  2013-08-06 11:31                   ` Lars-Peter Clausen
  2013-08-07  1:32                     ` Bard Liao
@ 2013-08-07  5:40                     ` Bard Liao
  2013-08-07  7:45                       ` Lars-Peter Clausen
  1 sibling, 1 reply; 35+ messages in thread
From: Bard Liao @ 2013-08-07  5:40 UTC (permalink / raw)
  To: Lars-Peter Clausen
  Cc: Oder Chiou, alsa-devel, swarren, swarren, lgirdwood, Mark Brown, Flove

Is there any way to run an event when power up/down a snd_soc_dapm_kcontrol type widgt?
Because we need to do something with mute/unmute headphone.
e.g.
rt5640_pmu_depop is what we need when unmute headphone.
We need to set something before and after set the hp mute bit.

If there is an event to do that, it will be easier to implement that.

Thanks.

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] ASoC: rt5640: change widgetsequencefordepop
  2013-08-07  5:40                     ` Bard Liao
@ 2013-08-07  7:45                       ` Lars-Peter Clausen
  2013-08-07  8:03                         ` Bard Liao
  0 siblings, 1 reply; 35+ messages in thread
From: Lars-Peter Clausen @ 2013-08-07  7:45 UTC (permalink / raw)
  To: Bard Liao
  Cc: Oder Chiou, alsa-devel, swarren, swarren, lgirdwood, Mark Brown, Flove

On 08/07/2013 07:40 AM, Bard Liao wrote:
> Is there any way to run an event when power up/down a snd_soc_dapm_kcontrol type widgt?
> Because we need to do something with mute/unmute headphone.
> e.g.
> rt5640_pmu_depop is what we need when unmute headphone.
> We need to set something before and after set the hp mute bit.
> 
> If there is an event to do that, it will be easier to implement that.

You can setup a event for the SND_SOC_DAPM_SWITCH, but this will run after
setting the mute bit and before clearing the mute bit.

- Lars

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] ASoC: rt5640: change widgetsequencefordepop
  2013-08-07  7:45                       ` Lars-Peter Clausen
@ 2013-08-07  8:03                         ` Bard Liao
  2013-08-07  8:26                           ` Lars-Peter Clausen
  0 siblings, 1 reply; 35+ messages in thread
From: Bard Liao @ 2013-08-07  8:03 UTC (permalink / raw)
  To: Lars-Peter Clausen
  Cc: Oder Chiou, alsa-devel, swarren, swarren, lgirdwood, Mark Brown, Flove

> -----Original Message-----
> From: Lars-Peter Clausen [mailto:lars@metafoo.de]
> Sent: Wednesday, August 07, 2013 3:45 PM
> To: Bard Liao
> Cc: Mark Brown; Oder Chiou; alsa-devel@alsa-project.org;
> swarren@nvidia.com; swarren@wwwdotorg.org; lgirdwood@gmail.com; Flove
> Subject: Re: [alsa-devel] [PATCH] ASoC: rt5640: change
> widgetsequencefordepop
> 
> On 08/07/2013 07:40 AM, Bard Liao wrote:
> > Is there any way to run an event when power up/down a
> snd_soc_dapm_kcontrol type widgt?
> > Because we need to do something with mute/unmute headphone.
> > e.g.
> > rt5640_pmu_depop is what we need when unmute headphone.
> > We need to set something before and after set the hp mute bit.
> >
> > If there is an event to do that, it will be easier to implement that.
> 
> You can setup a event for the SND_SOC_DAPM_SWITCH, but this will run after
> setting the mute bit and before clearing the mute bit.

It seems not to be suitable for me.
For me, It is better to run before setting the mute bit and after clearing the mute bit, too.

> 
> - Lars
> 
> 
> ------Please consider the environment before printing this e-mail.

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] ASoC: rt5640: change widgetsequencefordepop
  2013-08-07  8:03                         ` Bard Liao
@ 2013-08-07  8:26                           ` Lars-Peter Clausen
  2013-08-07  8:31                             ` Bard Liao
  2013-08-07  9:36                             ` Mark Brown
  0 siblings, 2 replies; 35+ messages in thread
From: Lars-Peter Clausen @ 2013-08-07  8:26 UTC (permalink / raw)
  To: Bard Liao
  Cc: Oder Chiou, alsa-devel, swarren, swarren, lgirdwood, Mark Brown, Flove

On 08/07/2013 10:03 AM, Bard Liao wrote:
>> -----Original Message-----
>> From: Lars-Peter Clausen [mailto:lars@metafoo.de]
>> Sent: Wednesday, August 07, 2013 3:45 PM
>> To: Bard Liao
>> Cc: Mark Brown; Oder Chiou; alsa-devel@alsa-project.org;
>> swarren@nvidia.com; swarren@wwwdotorg.org; lgirdwood@gmail.com; Flove
>> Subject: Re: [alsa-devel] [PATCH] ASoC: rt5640: change
>> widgetsequencefordepop
>>
>> On 08/07/2013 07:40 AM, Bard Liao wrote:
>>> Is there any way to run an event when power up/down a
>> snd_soc_dapm_kcontrol type widgt?
>>> Because we need to do something with mute/unmute headphone.
>>> e.g.
>>> rt5640_pmu_depop is what we need when unmute headphone.
>>> We need to set something before and after set the hp mute bit.
>>>
>>> If there is an event to do that, it will be easier to implement that.
>>
>> You can setup a event for the SND_SOC_DAPM_SWITCH, but this will run after
>> setting the mute bit and before clearing the mute bit.
> 
> It seems not to be suitable for me.
> For me, It is better to run before setting the mute bit and after clearing the mute bit, too.

That isn't really supported right now. If muting and unmuting the control is
such a complex sequence maybe it is better to stay with you previous
solution, without autodisable.

- Lars

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] ASoC: rt5640: change widgetsequencefordepop
  2013-08-07  8:26                           ` Lars-Peter Clausen
@ 2013-08-07  8:31                             ` Bard Liao
  2013-08-07  9:36                             ` Mark Brown
  1 sibling, 0 replies; 35+ messages in thread
From: Bard Liao @ 2013-08-07  8:31 UTC (permalink / raw)
  To: Lars-Peter Clausen
  Cc: Oder Chiou, alsa-devel, swarren, swarren, lgirdwood, Mark Brown, Flove

> -----Original Message-----
> From: Lars-Peter Clausen [mailto:lars@metafoo.de]
> Sent: Wednesday, August 07, 2013 4:27 PM
> To: Bard Liao
> Cc: Mark Brown; Oder Chiou; alsa-devel@alsa-project.org;
> swarren@nvidia.com; swarren@wwwdotorg.org; lgirdwood@gmail.com; Flove
> Subject: Re: [alsa-devel] [PATCH] ASoC: rt5640: change
> widgetsequencefordepop
> 
> On 08/07/2013 10:03 AM, Bard Liao wrote:
> >> -----Original Message-----
> >> From: Lars-Peter Clausen [mailto:lars@metafoo.de]
> >> Sent: Wednesday, August 07, 2013 3:45 PM
> >> To: Bard Liao
> >> Cc: Mark Brown; Oder Chiou; alsa-devel@alsa-project.org;
> >> swarren@nvidia.com; swarren@wwwdotorg.org; lgirdwood@gmail.com;
> Flove
> >> Subject: Re: [alsa-devel] [PATCH] ASoC: rt5640: change
> >> widgetsequencefordepop
> >>
> >> On 08/07/2013 07:40 AM, Bard Liao wrote:
> >>> Is there any way to run an event when power up/down a
> >> snd_soc_dapm_kcontrol type widgt?
> >>> Because we need to do something with mute/unmute headphone.
> >>> e.g.
> >>> rt5640_pmu_depop is what we need when unmute headphone.
> >>> We need to set something before and after set the hp mute bit.
> >>>
> >>> If there is an event to do that, it will be easier to implement that.
> >>
> >> You can setup a event for the SND_SOC_DAPM_SWITCH, but this will run
> >> after setting the mute bit and before clearing the mute bit.
> >
> > It seems not to be suitable for me.
> > For me, It is better to run before setting the mute bit and after clearing the
> mute bit, too.
> 
> That isn't really supported right now. If muting and unmuting the control is
> such a complex sequence maybe it is better to stay with you previous solution,
> without autodisable.

That's fine.
I will check with our HW engineer to see if there is a simple sequence for headphone muting and unmuting.

Thanks.

> 
> - Lars
> 
> 
> ------Please consider the environment before printing this e-mail.

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] ASoC: rt5640: change widgetsequencefordepop
  2013-08-07  8:26                           ` Lars-Peter Clausen
  2013-08-07  8:31                             ` Bard Liao
@ 2013-08-07  9:36                             ` Mark Brown
  2013-08-07 10:47                               ` Lars-Peter Clausen
  1 sibling, 1 reply; 35+ messages in thread
From: Mark Brown @ 2013-08-07  9:36 UTC (permalink / raw)
  To: Lars-Peter Clausen
  Cc: Oder Chiou, alsa-devel, swarren, swarren, lgirdwood, Bard Liao, Flove


[-- Attachment #1.1: Type: text/plain, Size: 297 bytes --]

On Wed, Aug 07, 2013 at 10:26:35AM +0200, Lars-Peter Clausen wrote:

> That isn't really supported right now. If muting and unmuting the control is
> such a complex sequence maybe it is better to stay with you previous
> solution, without autodisable.

Adding an event callback shouldn't be hard?

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] ASoC: rt5640: change widgetsequencefordepop
  2013-08-07  9:36                             ` Mark Brown
@ 2013-08-07 10:47                               ` Lars-Peter Clausen
  2013-08-07 13:05                                 ` Mark Brown
  2013-08-09  9:05                                 ` Bard Liao
  0 siblings, 2 replies; 35+ messages in thread
From: Lars-Peter Clausen @ 2013-08-07 10:47 UTC (permalink / raw)
  To: Mark Brown
  Cc: Oder Chiou, alsa-devel, swarren, swarren, lgirdwood, Bard Liao, Flove

On 08/07/2013 11:36 AM, Mark Brown wrote:
> On Wed, Aug 07, 2013 at 10:26:35AM +0200, Lars-Peter Clausen wrote:
>
>> That isn't really supported right now. If muting and unmuting the control is
>> such a complex sequence maybe it is better to stay with you previous
>> solution, without autodisable.
>
> Adding an event callback shouldn't be hard?
>

But tricky. The widget of course can have a event callback, but since the 
widget is created by the DAPM layer and not the codec driver there is currently 
no way to setup the callback. And then there is of course the question when do 
you want to run the callback, only if DAPM unmutes the control, if the user 
unmutes the control or both.

One thing that could work is to setup SND_SOC_DAPM_{PRE,POST}_REG events for 
the SWITCH widget. This callback gets called whenever user changes the control 
(and it is not disabled by DAPM). The next step then would be to set up an 
internal event callback for kcontrol widgets which then again calls the event 
callbacks for the kcontrol's widgets like we do in dapm_widget_update(). But 
I'm not convinced that this is the best way to solve this. I think it makes 
things more complicated than they need to be. I think having a OUTDRV widget 
along the path that runs the mute and unmute sequence might be a better option. 
And then have virtual switch control to let userspace disconnect the path, so 
that it is still possbile to manually mute it.

- Lars

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] ASoC: rt5640: change widgetsequencefordepop
  2013-08-07 10:47                               ` Lars-Peter Clausen
@ 2013-08-07 13:05                                 ` Mark Brown
  2013-08-09  9:05                                 ` Bard Liao
  1 sibling, 0 replies; 35+ messages in thread
From: Mark Brown @ 2013-08-07 13:05 UTC (permalink / raw)
  To: Lars-Peter Clausen
  Cc: Oder Chiou, alsa-devel, swarren, swarren, lgirdwood, Bard Liao, Flove


[-- Attachment #1.1: Type: text/plain, Size: 1452 bytes --]

On Wed, Aug 07, 2013 at 12:47:16PM +0200, Lars-Peter Clausen wrote:
> On 08/07/2013 11:36 AM, Mark Brown wrote:

> >Adding an event callback shouldn't be hard?

> But tricky. The widget of course can have a event callback, but
> since the widget is created by the DAPM layer and not the codec
> driver there is currently no way to setup the callback. And then
> there is of course the question when do you want to run the
> callback, only if DAPM unmutes the control, if the user unmutes the
> control or both.

I'd expect to run any time we actually interact with the hardware.

> One thing that could work is to setup SND_SOC_DAPM_{PRE,POST}_REG
> events for the SWITCH widget. This callback gets called whenever
> user changes the control (and it is not disabled by DAPM). The next
> step then would be to set up an internal event callback for kcontrol
> widgets which then again calls the event callbacks for the
> kcontrol's widgets like we do in dapm_widget_update(). But I'm not
> convinced that this is the best way to solve this. I think it makes
> things more complicated than they need to be. I think having a
> OUTDRV widget along the path that runs the mute and unmute sequence
> might be a better option. And then have virtual switch control to
> let userspace disconnect the path, so that it is still possbile to
> manually mute it.

This only works for mute and unmute, it won't work for things like fun
sequences to do volume changes.

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] ASoC: rt5640: change widgetsequencefordepop
  2013-08-07 10:47                               ` Lars-Peter Clausen
  2013-08-07 13:05                                 ` Mark Brown
@ 2013-08-09  9:05                                 ` Bard Liao
  2013-08-09 13:37                                   ` Lars-Peter Clausen
  1 sibling, 1 reply; 35+ messages in thread
From: Bard Liao @ 2013-08-09  9:05 UTC (permalink / raw)
  To: Lars-Peter Clausen, Mark Brown
  Cc: Oder Chiou, alsa-devel, swarren, swarren, lgirdwood, Flove

> One thing that could work is to setup SND_SOC_DAPM_{PRE,POST}_REG
> events for the SWITCH widget. This callback gets called whenever user
> changes the control (and it is not disabled by DAPM). The next step then would
> be to set up an internal event callback for kcontrol widgets which then again
> calls the event callbacks for the kcontrol's widgets like we do in
> dapm_widget_update(). But I'm not convinced that this is the best way to solve
> this. I think it makes things more complicated than they need to be. I think
> having a OUTDRV widget along the path that runs the mute and unmute
> sequence might be a better option.
> And then have virtual switch control to let userspace disconnect the path, so
> that it is still possbile to manually mute it.

Does "virtual switch control" mean a switch control which will not touch the codec's register actually?

> 
> - Lars
> 
> ------Please consider the environment before printing this e-mail.

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] ASoC: rt5640: change widgetsequencefordepop
  2013-08-09  9:05                                 ` Bard Liao
@ 2013-08-09 13:37                                   ` Lars-Peter Clausen
  2013-08-09 14:58                                     ` Mark Brown
  0 siblings, 1 reply; 35+ messages in thread
From: Lars-Peter Clausen @ 2013-08-09 13:37 UTC (permalink / raw)
  To: Bard Liao
  Cc: Oder Chiou, alsa-devel, swarren, swarren, lgirdwood, Mark Brown, Flove

On 08/09/2013 11:05 AM, Bard Liao wrote:
>> One thing that could work is to setup SND_SOC_DAPM_{PRE,POST}_REG
>> events for the SWITCH widget. This callback gets called whenever user
>> changes the control (and it is not disabled by DAPM). The next step then would
>> be to set up an internal event callback for kcontrol widgets which then again
>> calls the event callbacks for the kcontrol's widgets like we do in
>> dapm_widget_update(). But I'm not convinced that this is the best way to solve
>> this. I think it makes things more complicated than they need to be. I think
>> having a OUTDRV widget along the path that runs the mute and unmute
>> sequence might be a better option.
>> And then have virtual switch control to let userspace disconnect the path, so
>> that it is still possbile to manually mute it.
> 
> Does "virtual switch control" mean a switch control which will not touch the codec's register actually?

Yes. But Mark seems to prefer the solution using {PRE,POST}_REG events.

- Lars

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] ASoC: rt5640: change widgetsequencefordepop
  2013-08-09 13:37                                   ` Lars-Peter Clausen
@ 2013-08-09 14:58                                     ` Mark Brown
  2013-08-12  7:27                                       ` Bard Liao
  0 siblings, 1 reply; 35+ messages in thread
From: Mark Brown @ 2013-08-09 14:58 UTC (permalink / raw)
  To: Lars-Peter Clausen
  Cc: Oder Chiou, alsa-devel, swarren, swarren, lgirdwood, Bard Liao, Flove


[-- Attachment #1.1: Type: text/plain, Size: 371 bytes --]

On Fri, Aug 09, 2013 at 03:37:46PM +0200, Lars-Peter Clausen wrote:
> On 08/09/2013 11:05 AM, Bard Liao wrote:

> > Does "virtual switch control" mean a switch control which will not touch the codec's register actually?

> Yes. But Mark seems to prefer the solution using {PRE,POST}_REG events.

I don't mind that much, neither way should be a problem for the
framework.

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] ASoC: rt5640: change widgetsequencefordepop
  2013-08-09 14:58                                     ` Mark Brown
@ 2013-08-12  7:27                                       ` Bard Liao
  0 siblings, 0 replies; 35+ messages in thread
From: Bard Liao @ 2013-08-12  7:27 UTC (permalink / raw)
  To: Mark Brown, Lars-Peter Clausen
  Cc: Oder Chiou, alsa-devel, swarren, swarren, lgirdwood, Flove

> -----Original Message-----
> From: Mark Brown [mailto:broonie@kernel.org]
> Sent: Friday, August 09, 2013 10:59 PM
> To: Lars-Peter Clausen
> Cc: Bard Liao; Oder Chiou; alsa-devel@alsa-project.org; swarren@nvidia.com;
> swarren@wwwdotorg.org; lgirdwood@gmail.com; Flove
> Subject: Re: [alsa-devel] [PATCH] ASoC: rt5640: change
> widgetsequencefordepop
> 
> On Fri, Aug 09, 2013 at 03:37:46PM +0200, Lars-Peter Clausen wrote:
> > On 08/09/2013 11:05 AM, Bard Liao wrote:
> 
> > > Does "virtual switch control" mean a switch control which will not touch
> the codec's register actually?
> 
> > Yes. But Mark seems to prefer the solution using {PRE,POST}_REG events.
> 
> I don't mind that much, neither way should be a problem for the framework.

Does SOC_DAPM_SINGLE_AUTODISABLE support SND_SOC_DAPM_{PRE,POST}_REG event?
It seems SND_SOC_DAPM_{PRE,POST}_REG event is supported in SOC_DAPM_SINGLE but not in SOC_DAPM_SINGLE_AUTODISABLE.

> 
> ------Please consider the environment before printing this e-mail.

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] ASoC: rt5640: change widget sequence for depop
  2013-08-20 16:15     ` Stephen Warren
@ 2013-08-21 19:56       ` Lars-Peter Clausen
  0 siblings, 0 replies; 35+ messages in thread
From: Lars-Peter Clausen @ 2013-08-21 19:56 UTC (permalink / raw)
  To: Stephen Warren
  Cc: Oder Chiou, alsa-devel, swarren, lgirdwood, broonie, Bard Liao, Flove

On 08/20/2013 06:15 PM, Stephen Warren wrote:
[...]
> Lars-Peter, are you planning on sending the change above as a patch for
> Mark to apply?

I will send the patch next week, once I'm back from vacation.

- Lars

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] ASoC: rt5640: change widget sequence for depop
  2013-08-20  2:36   ` Bard Liao
@ 2013-08-20 16:15     ` Stephen Warren
  2013-08-21 19:56       ` Lars-Peter Clausen
  0 siblings, 1 reply; 35+ messages in thread
From: Stephen Warren @ 2013-08-20 16:15 UTC (permalink / raw)
  To: Bard Liao
  Cc: Oder Chiou, alsa-devel, Lars-Peter Clausen, swarren, lgirdwood,
	broonie, Flove

On 08/19/2013 08:36 PM, Bard Liao wrote:
>> -----Original Message-----
>> From: Stephen Warren [mailto:swarren@wwwdotorg.org]
>> Sent: Tuesday, August 20, 2013 1:30 AM
>> To: Bard Liao
>> Cc: broonie@kernel.org; lgirdwood@gmail.com; alsa-devel@alsa-project.org;
>> Flove; Oder Chiou; swarren@nvidia.com
>> Subject: Re: [PATCH] ASoC: rt5640: change widget sequence for depop
>>
>> On 08/19/2013 06:18 AM, bardliao@realtek.com wrote:
>>> From: Bard Liao <bardliao@realtek.com>
>>>
>>> Add mute/unmute control in widget event and modify the power on/off
>> sequence to avoid pop noise.
>>
>> This version breaks both headphone and speaker output. I see the following
>> issues:
>>
>> 1)
>>
>> After a reboot, if all of "{HP,Speaker} [LR] Playback Switch" are on/unmuted,
>> and I start playback, then something sets all those controls to off/muted. I
>> suspect this is related to function rt5640_hp_event() twiddling the same
>> RT5640_[LR]_MUTE bits that the hp_[lr]_enable_control controls twiddle.
>>
>> 2)
>>
>> If playback is running, and (1) has caused all output to be muted, and I then
>> run alsamixer and enable/unmute "HP L Playback Switch", I hear sound on
>> both the L and R headphone channels for a very brief time, then output
>> switches to the L channel only. Similar happens if I unmute "HP R Playback
>> Switch" first. Unmuting both switches does produce stereo sound as expected.
>>
>> I don't know if this also happens for the speaker output, since the board is too
>> far away from me to easily tell which speakers are playing.
> 
> I think you didn't apply Lars-Peter's patch as below.
> --- a/sound/soc/soc-dapm.c
> +++ b/sound/soc/soc-dapm.c
> @@ -229,6 +229,8 @@ static int dapm_kcontrol_data_alloc(struct
>   			template.id = snd_soc_dapm_kcontrol;
>   			template.name = kcontrol->id.name;
> 
> +			data->value = template.on_val;
> +
>   			data->widget = snd_soc_dapm_new_control(widget->dapm,
>   				&template);
>   			if (!data->widget) {
> 
> It should be able to solve this issue.
> If I remove this patch I can reproduce the issue.
> Sorry for not informing you about that.

As far as I can tell, Lars-Peter hasn't actually sent such a patch to
the list; he simply mentioned this change inline in the middle of a
thread following an earlier version of this patch.

Lars-Peter, are you planning on sending the change above as a patch for
Mark to apply?

With that patch also applied, symptom (1) I mentioned above is indeed
fixed. However, symptom is still observed.

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] ASoC: rt5640: change widget sequence for depop
  2013-08-19 17:29 ` Stephen Warren
@ 2013-08-20  2:36   ` Bard Liao
  2013-08-20 16:15     ` Stephen Warren
  0 siblings, 1 reply; 35+ messages in thread
From: Bard Liao @ 2013-08-20  2:36 UTC (permalink / raw)
  To: Stephen Warren; +Cc: Oder Chiou, alsa-devel, swarren, lgirdwood, broonie, Flove

> -----Original Message-----
> From: Stephen Warren [mailto:swarren@wwwdotorg.org]
> Sent: Tuesday, August 20, 2013 1:30 AM
> To: Bard Liao
> Cc: broonie@kernel.org; lgirdwood@gmail.com; alsa-devel@alsa-project.org;
> Flove; Oder Chiou; swarren@nvidia.com
> Subject: Re: [PATCH] ASoC: rt5640: change widget sequence for depop
> 
> On 08/19/2013 06:18 AM, bardliao@realtek.com wrote:
> > From: Bard Liao <bardliao@realtek.com>
> >
> > Add mute/unmute control in widget event and modify the power on/off
> sequence to avoid pop noise.
> 
> This version breaks both headphone and speaker output. I see the following
> issues:
> 
> 1)
> 
> After a reboot, if all of "{HP,Speaker} [LR] Playback Switch" are on/unmuted,
> and I start playback, then something sets all those controls to off/muted. I
> suspect this is related to function rt5640_hp_event() twiddling the same
> RT5640_[LR]_MUTE bits that the hp_[lr]_enable_control controls twiddle.
> 
> 2)
> 
> If playback is running, and (1) has caused all output to be muted, and I then
> run alsamixer and enable/unmute "HP L Playback Switch", I hear sound on
> both the L and R headphone channels for a very brief time, then output
> switches to the L channel only. Similar happens if I unmute "HP R Playback
> Switch" first. Unmuting both switches does produce stereo sound as expected.
> 
> I don't know if this also happens for the speaker output, since the board is too
> far away from me to easily tell which speakers are playing.

I think you didn't apply Lars-Peter's patch as below.
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -229,6 +229,8 @@ static int dapm_kcontrol_data_alloc(struct
  			template.id = snd_soc_dapm_kcontrol;
  			template.name = kcontrol->id.name;

+			data->value = template.on_val;
+
  			data->widget = snd_soc_dapm_new_control(widget->dapm,
  				&template);
  			if (!data->widget) {

It should be able to solve this issue.
If I remove this patch I can reproduce the issue.
Sorry for not informing you about that.

> 
> ------Please consider the environment before printing this e-mail.

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] ASoC: rt5640: change widget sequence for depop
  2013-08-19 12:18 bardliao
@ 2013-08-19 17:29 ` Stephen Warren
  2013-08-20  2:36   ` Bard Liao
  0 siblings, 1 reply; 35+ messages in thread
From: Stephen Warren @ 2013-08-19 17:29 UTC (permalink / raw)
  To: bardliao; +Cc: oder_chiou, alsa-devel, swarren, lgirdwood, broonie, flove

On 08/19/2013 06:18 AM, bardliao@realtek.com wrote:
> From: Bard Liao <bardliao@realtek.com>
> 
> Add mute/unmute control in widget event and modify the power on/off sequence to avoid pop noise.

This version breaks both headphone and speaker output. I see the
following issues:

1)

After a reboot, if all of "{HP,Speaker} [LR] Playback Switch" are
on/unmuted, and I start playback, then something sets all those controls
to off/muted. I suspect this is related to function rt5640_hp_event()
twiddling the same RT5640_[LR]_MUTE bits that the hp_[lr]_enable_control
controls twiddle.

2)

If playback is running, and (1) has caused all output to be muted, and I
then run alsamixer and enable/unmute "HP L Playback Switch", I hear
sound on both the L and R headphone channels for a very brief time, then
output switches to the L channel only. Similar happens if I unmute "HP R
Playback Switch" first. Unmuting both switches does produce stereo sound
as expected.

I don't know if this also happens for the speaker output, since the
board is too far away from me to easily tell which speakers are playing.

^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH] ASoC: rt5640: change widget sequence for depop
@ 2013-08-19 12:18 bardliao
  2013-08-19 17:29 ` Stephen Warren
  0 siblings, 1 reply; 35+ messages in thread
From: bardliao @ 2013-08-19 12:18 UTC (permalink / raw)
  To: broonie, lgirdwood
  Cc: oder_chiou, alsa-devel, swarren, swarren, bardliao, flove

From: Bard Liao <bardliao@realtek.com>

Add mute/unmute control in widget event and modify the power on/off sequence to avoid pop noise.

Signed-off-by: Bard Liao <bardliao@realtek.com>
---
 sound/soc/codecs/rt5640.c | 200 +++++++++++++++++++++++++++++++++-------------
 sound/soc/codecs/rt5640.h |  11 +++
 2 files changed, 157 insertions(+), 54 deletions(-)

diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index 4db7314..218aae2 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -50,8 +50,6 @@ static const struct regmap_range_cfg rt5640_ranges[] = {
 
 static struct reg_default init_list[] = {
 	{RT5640_PR_BASE + 0x3d,	0x3600},
-	{RT5640_PR_BASE + 0x1c,	0x0D21},
-	{RT5640_PR_BASE + 0x1b,	0x0000},
 	{RT5640_PR_BASE + 0x12,	0x0aa8},
 	{RT5640_PR_BASE + 0x14,	0x0aaa},
 	{RT5640_PR_BASE + 0x20,	0x6110},
@@ -384,15 +382,11 @@ static const SOC_ENUM_SINGLE_DECL(
 
 static const struct snd_kcontrol_new rt5640_snd_controls[] = {
 	/* Speaker Output Volume */
-	SOC_DOUBLE("Speaker Playback Switch", RT5640_SPK_VOL,
-		RT5640_L_MUTE_SFT, RT5640_R_MUTE_SFT, 1, 1),
 	SOC_DOUBLE("Speaker Channel Switch", RT5640_SPK_VOL,
 		RT5640_VOL_L_SFT, RT5640_VOL_R_SFT, 1, 1),
 	SOC_DOUBLE_TLV("Speaker Playback Volume", RT5640_SPK_VOL,
 		RT5640_L_VOL_SFT, RT5640_R_VOL_SFT, 39, 1, out_vol_tlv),
 	/* Headphone Output Volume */
-	SOC_DOUBLE("HP Playback Switch", RT5640_HP_VOL,
-		RT5640_L_MUTE_SFT, RT5640_R_MUTE_SFT, 1, 1),
 	SOC_DOUBLE("HP Channel Switch", RT5640_HP_VOL,
 		RT5640_VOL_L_SFT, RT5640_VOL_R_SFT, 1, 1),
 	SOC_DOUBLE_TLV("HP Playback Volume", RT5640_HP_VOL,
@@ -737,6 +731,22 @@ static const struct snd_kcontrol_new rt5640_mono_mix[] = {
 			RT5640_M_BST1_MM_SFT, 1, 1),
 };
 
+static const struct snd_kcontrol_new spk_l_enable_control =
+	SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5640_SPK_VOL,
+		RT5640_L_MUTE_SFT, 1, 1);
+
+static const struct snd_kcontrol_new spk_r_enable_control =
+	SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5640_SPK_VOL,
+		RT5640_R_MUTE_SFT, 1, 1);
+
+static const struct snd_kcontrol_new hp_l_enable_control =
+	SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5640_HP_VOL,
+		RT5640_L_MUTE_SFT, 1, 1);
+
+static const struct snd_kcontrol_new hp_r_enable_control =
+	SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5640_HP_VOL,
+		RT5640_R_MUTE_SFT, 1, 1);
+
 /* Stereo ADC source */
 static const char * const rt5640_stereo_adc1_src[] = {
 	"DIG MIX", "ADC"
@@ -868,33 +878,6 @@ static const SOC_ENUM_SINGLE_DECL(
 static const struct snd_kcontrol_new rt5640_sdi_mux =
 	SOC_DAPM_ENUM("SDI select", rt5640_sdi_sel_enum);
 
-static int spk_event(struct snd_soc_dapm_widget *w,
-	struct snd_kcontrol *kcontrol, int event)
-{
-	struct snd_soc_codec *codec = w->codec;
-	struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
-
-	switch (event) {
-	case SND_SOC_DAPM_POST_PMU:
-		regmap_update_bits(rt5640->regmap, RT5640_PWR_DIG1,
-					0x0001, 0x0001);
-		regmap_update_bits(rt5640->regmap, RT5640_PR_BASE + 0x1c,
-					0xf000, 0xf000);
-		break;
-
-	case SND_SOC_DAPM_PRE_PMD:
-		regmap_update_bits(rt5640->regmap, RT5640_PR_BASE + 0x1c,
-					0xf000, 0x0000);
-		regmap_update_bits(rt5640->regmap, RT5640_PWR_DIG1,
-					0x0001, 0x0000);
-		break;
-
-	default:
-		return 0;
-	}
-	return 0;
-}
-
 static int rt5640_set_dmic1_event(struct snd_soc_dapm_widget *w,
 	struct snd_kcontrol *kcontrol, int event)
 {
@@ -943,6 +926,103 @@ static int rt5640_set_dmic2_event(struct snd_soc_dapm_widget *w,
 	return 0;
 }
 
+void hp_amp_power_on(struct snd_soc_codec *codec)
+{
+	struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
+
+	/* depop parameters */
+	regmap_update_bits(rt5640->regmap, RT5640_PR_BASE +
+		RT5640_CHPUMP_INT_REG1, 0x0700, 0x0200);
+	regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M2,
+		RT5640_DEPOP_MASK, RT5640_DEPOP_MAN);
+	regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M1,
+		RT5640_HP_CP_MASK | RT5640_HP_SG_MASK | RT5640_HP_CB_MASK,
+		RT5640_HP_CP_PU | RT5640_HP_SG_DIS | RT5640_HP_CB_PU);
+	regmap_write(rt5640->regmap, RT5640_PR_BASE + RT5640_HP_DCC_INT1,
+			   0x9f00);
+	/* headphone amp power on */
+	regmap_update_bits(rt5640->regmap, RT5640_PWR_ANLG1,
+		RT5640_PWR_FV1 | RT5640_PWR_FV2, 0);
+	regmap_update_bits(rt5640->regmap, RT5640_PWR_ANLG1,
+		RT5640_PWR_HA,
+		RT5640_PWR_HA);
+	usleep_range(30000, 35000);
+	regmap_update_bits(rt5640->regmap, RT5640_PWR_ANLG1,
+		RT5640_PWR_FV1 | RT5640_PWR_FV2 ,
+		RT5640_PWR_FV1 | RT5640_PWR_FV2);
+}
+
+static void rt5640_pmu_depop(struct snd_soc_codec *codec)
+{
+	struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
+
+	regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M2,
+		RT5640_DEPOP_MASK | RT5640_DIG_DP_MASK,
+		RT5640_DEPOP_AUTO | RT5640_DIG_DP_EN);
+	regmap_update_bits(rt5640->regmap, RT5640_CHARGE_PUMP,
+		RT5640_PM_HP_MASK, RT5640_PM_HP_HV);
+
+	regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M3,
+		RT5640_CP_FQ1_MASK | RT5640_CP_FQ2_MASK | RT5640_CP_FQ3_MASK,
+		(RT5640_CP_FQ_192_KHZ << RT5640_CP_FQ1_SFT) |
+		(RT5640_CP_FQ_12_KHZ << RT5640_CP_FQ2_SFT) |
+		(RT5640_CP_FQ_192_KHZ << RT5640_CP_FQ3_SFT));
+
+	regmap_write(rt5640->regmap, RT5640_PR_BASE +
+		RT5640_MAMP_INT_REG2, 0x1c00);
+	regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M1,
+		RT5640_HP_CP_MASK | RT5640_HP_SG_MASK,
+		RT5640_HP_CP_PD | RT5640_HP_SG_EN);
+	regmap_update_bits(rt5640->regmap, RT5640_PR_BASE +
+		RT5640_CHPUMP_INT_REG1, 0x0700, 0x0400);
+}
+
+static int rt5640_hp_event(struct snd_soc_dapm_widget *w,
+			   struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	unsigned int val = 0, pow;
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		rt5640_pmu_depop(codec);
+		pow = snd_soc_read(codec,  RT5640_PWR_ANLG1);
+		if (!(pow & RT5640_PWR_HP_L))
+			val |= RT5640_L_MUTE;
+		if (!(pow & RT5640_PWR_HP_R))
+			val |= RT5640_R_MUTE;
+		snd_soc_update_bits(codec, RT5640_HP_VOL,
+			RT5640_L_MUTE | RT5640_R_MUTE, val);
+		usleep_range(35000, 40000);
+		break;
+
+	case SND_SOC_DAPM_PRE_PMD:
+		usleep_range(70000, 75000);
+		break;
+
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
+static int rt5640_hp_power_event(struct snd_soc_dapm_widget *w,
+			   struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		hp_amp_power_on(codec);
+		break;
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
 static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = {
 	SND_SOC_DAPM_SUPPLY("PLL1", RT5640_PWR_ANLG2,
 			RT5640_PWR_PLL_BIT, 0, NULL, 0),
@@ -1132,15 +1212,27 @@ static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = {
 		rt5640_mono_mix, ARRAY_SIZE(rt5640_mono_mix)),
 	SND_SOC_DAPM_SUPPLY("Improve MONO Amp Drv", RT5640_PWR_ANLG1,
 		RT5640_PWR_MA_BIT, 0, NULL, 0),
-	SND_SOC_DAPM_SUPPLY("Improve HP Amp Drv", RT5640_PWR_ANLG1,
-		SND_SOC_NOPM, 0, NULL, 0),
-	SND_SOC_DAPM_PGA("HP L Amp", RT5640_PWR_ANLG1,
+	SND_SOC_DAPM_SUPPLY_S("Improve HP Amp Drv", 1, SND_SOC_NOPM,
+		0, 0, rt5640_hp_power_event, SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_PGA_S("HP Amp", 1, SND_SOC_NOPM, 0, 0,
+		rt5640_hp_event,
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_SUPPLY("HP L Amp", RT5640_PWR_ANLG1,
 		RT5640_PWR_HP_L_BIT, 0, NULL, 0),
-	SND_SOC_DAPM_PGA("HP R Amp", RT5640_PWR_ANLG1,
+	SND_SOC_DAPM_SUPPLY("HP R Amp", RT5640_PWR_ANLG1,
 		RT5640_PWR_HP_R_BIT, 0, NULL, 0),
 	SND_SOC_DAPM_SUPPLY("Improve SPK Amp Drv", RT5640_PWR_DIG1,
-		SND_SOC_NOPM, 0, spk_event,
-		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+		RT5640_PWR_CLS_D_BIT, 0, NULL, 0),
+
+	/* Output Switch */
+	SND_SOC_DAPM_SWITCH("Speaker L Playback", SND_SOC_NOPM, 0, 0,
+			&spk_l_enable_control),
+	SND_SOC_DAPM_SWITCH("Speaker R Playback", SND_SOC_NOPM, 0, 0,
+			&spk_r_enable_control),
+	SND_SOC_DAPM_SWITCH("HP L Playback", SND_SOC_NOPM, 0, 0,
+			&hp_l_enable_control),
+	SND_SOC_DAPM_SWITCH("HP R Playback", SND_SOC_NOPM, 0, 0,
+			&hp_r_enable_control),
 	/* Output Lines */
 	SND_SOC_DAPM_OUTPUT("SPOLP"),
 	SND_SOC_DAPM_OUTPUT("SPOLN"),
@@ -1381,9 +1473,11 @@ static const struct snd_soc_dapm_route rt5640_dapm_routes[] = {
 	{"HPO MIX L", "HPO MIX DAC2 Switch", "DAC L2"},
 	{"HPO MIX L", "HPO MIX DAC1 Switch", "DAC L1"},
 	{"HPO MIX L", "HPO MIX HPVOL Switch", "HPOVOL L"},
+	{"HPO MIX L", NULL, "HP L Amp"},
 	{"HPO MIX R", "HPO MIX DAC2 Switch", "DAC R2"},
 	{"HPO MIX R", "HPO MIX DAC1 Switch", "DAC R1"},
 	{"HPO MIX R", "HPO MIX HPVOL Switch", "HPOVOL R"},
+	{"HPO MIX R", NULL, "HP R Amp"},
 
 	{"LOUT MIX", "DAC L1 Switch", "DAC L1"},
 	{"LOUT MIX", "DAC R1 Switch", "DAC R1"},
@@ -1396,13 +1490,15 @@ static const struct snd_soc_dapm_route rt5640_dapm_routes[] = {
 	{"Mono MIX", "OUTVOL L Switch", "OUTVOL L"},
 	{"Mono MIX", "BST1 Switch", "BST1"},
 
-	{"HP L Amp", NULL, "HPO MIX L"},
-	{"HP R Amp", NULL, "HPO MIX R"},
+	{"HP Amp", NULL, "HPO MIX L"},
+	{"HP Amp", NULL, "HPO MIX R"},
 
-	{"SPOLP", NULL, "SPOL MIX"},
-	{"SPOLN", NULL, "SPOL MIX"},
-	{"SPORP", NULL, "SPOR MIX"},
-	{"SPORN", NULL, "SPOR MIX"},
+	{"Speaker L Playback", "Switch", "SPOL MIX"},
+	{"Speaker R Playback", "Switch", "SPOR MIX"},
+	{"SPOLP", NULL, "Speaker L Playback"},
+	{"SPOLN", NULL, "Speaker L Playback"},
+	{"SPORP", NULL, "Speaker R Playback"},
+	{"SPORN", NULL, "Speaker R Playback"},
 
 	{"SPOLP", NULL, "Improve SPK Amp Drv"},
 	{"SPOLN", NULL, "Improve SPK Amp Drv"},
@@ -1412,8 +1508,10 @@ static const struct snd_soc_dapm_route rt5640_dapm_routes[] = {
 	{"HPOL", NULL, "Improve HP Amp Drv"},
 	{"HPOR", NULL, "Improve HP Amp Drv"},
 
-	{"HPOL", NULL, "HP L Amp"},
-	{"HPOR", NULL, "HP R Amp"},
+	{"HP L Playback", "Switch", "HP Amp"},
+	{"HP R Playback", "Switch", "HP Amp"},
+	{"HPOL", NULL, "HP L Playback"},
+	{"HPOR", NULL, "HP R Playback"},
 	{"LOUTL", NULL, "LOUT MIX"},
 	{"LOUTR", NULL, "LOUT MIX"},
 	{"MONOP", NULL, "Mono MIX"},
@@ -1792,17 +1890,13 @@ static int rt5640_set_bias_level(struct snd_soc_codec *codec,
 				RT5640_PWR_BG | RT5640_PWR_VREF2,
 				RT5640_PWR_VREF1 | RT5640_PWR_MB |
 				RT5640_PWR_BG | RT5640_PWR_VREF2);
-			mdelay(10);
+			usleep_range(15000, 20000);
 			snd_soc_update_bits(codec, RT5640_PWR_ANLG1,
 				RT5640_PWR_FV1 | RT5640_PWR_FV2,
 				RT5640_PWR_FV1 | RT5640_PWR_FV2);
 			regcache_sync(rt5640->regmap);
 			snd_soc_update_bits(codec, RT5640_DUMMY1,
 						0x0301, 0x0301);
-			snd_soc_update_bits(codec, RT5640_DEPOP_M1,
-						0x001d, 0x0019);
-			snd_soc_update_bits(codec, RT5640_DEPOP_M2,
-						0x2000, 0x2000);
 			snd_soc_update_bits(codec, RT5640_MICBIAS,
 						0x0030, 0x0030);
 		}
@@ -1846,8 +1940,6 @@ static int rt5640_probe(struct snd_soc_codec *codec)
 	rt5640_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
 	snd_soc_update_bits(codec, RT5640_DUMMY1, 0x0301, 0x0301);
-	snd_soc_update_bits(codec, RT5640_DEPOP_M1, 0x001d, 0x0019);
-	snd_soc_update_bits(codec, RT5640_DEPOP_M2, 0x2000, 0x2000);
 	snd_soc_update_bits(codec, RT5640_MICBIAS, 0x0030, 0x0030);
 	snd_soc_update_bits(codec, RT5640_DSP_PATH2, 0xfc00, 0x0c00);
 
diff --git a/sound/soc/codecs/rt5640.h b/sound/soc/codecs/rt5640.h
index c48286d..4d2cfe7 100644
--- a/sound/soc/codecs/rt5640.h
+++ b/sound/soc/codecs/rt5640.h
@@ -145,6 +145,8 @@
 
 
 /* Index of Codec Private Register definition */
+#define RT5640_CHPUMP_INT_REG1			0x24
+#define RT5640_MAMP_INT_REG2			0x37
 #define RT5640_3D_SPK				0x63
 #define RT5640_WND_1				0x6c
 #define RT5640_WND_2				0x6d
@@ -153,6 +155,7 @@
 #define RT5640_WND_5				0x70
 #define RT5640_WND_8				0x73
 #define RT5640_DIP_SPK_INF			0x75
+#define RT5640_HP_DCC_INT1			0x77
 #define RT5640_EQ_BW_LOP			0xa0
 #define RT5640_EQ_GN_LOP			0xa1
 #define RT5640_EQ_FC_BP1			0xa2
@@ -1201,6 +1204,14 @@
 #define RT5640_CP_FQ2_SFT			4
 #define RT5640_CP_FQ3_MASK			(0x7)
 #define RT5640_CP_FQ3_SFT			0
+#define RT5640_CP_FQ_1_5_KHZ			0
+#define RT5640_CP_FQ_3_KHZ			1
+#define RT5640_CP_FQ_6_KHZ			2
+#define RT5640_CP_FQ_12_KHZ			3
+#define RT5640_CP_FQ_24_KHZ			4
+#define RT5640_CP_FQ_48_KHZ			5
+#define RT5640_CP_FQ_96_KHZ			6
+#define RT5640_CP_FQ_192_KHZ			7
 
 /* HPOUT charge pump (0x91) */
 #define RT5640_OSW_L_MASK			(0x1 << 11)
-- 
1.8.1.1.439.g50a6b54

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* Re: [PATCH] ASoC: rt5640: change widget sequence for depop
  2013-08-02 15:53 ` Stephen Warren
@ 2013-08-05  3:34   ` Bard Liao
  0 siblings, 0 replies; 35+ messages in thread
From: Bard Liao @ 2013-08-05  3:34 UTC (permalink / raw)
  To: Stephen Warren; +Cc: Oder Chiou, alsa-devel, swarren, lgirdwood, broonie, Flove

> -----Original Message-----
> From: Stephen Warren [mailto:swarren@wwwdotorg.org]
> Sent: Friday, August 02, 2013 11:54 PM
> To: Bard Liao
> Cc: broonie@kernel.org; lgirdwood@gmail.com; alsa-devel@alsa-project.org;
> Flove; Oder Chiou; swarren@nvidia.com
> Subject: Re: [PATCH] ASoC: rt5640: change widget sequence for depop
> 
> On 08/01/2013 08:38 PM, bardliao@realtek.com wrote:
> > From: Bard Liao <bardliao@realtek.com>
> >
> > Add mute/unmute control in widget event and modify the power on/off
> sequence to avoid pop noise.
> 
> So, this does seem to improve (remove) pop noise on headphones. However, it
> also completely prevents speakers from working. Do you know what the
> problem is there?

I am sorry about that.
I tested it without a physical speaker connected but only checked the reg values.
Now, I have a speaker connected on my T40 board.
I will update the patch in a short time.

Thanks.

> 
> ------Please consider the environment before printing this e-mail.

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH] ASoC: rt5640: change widget sequence for depop
  2013-08-02  2:38 bardliao
@ 2013-08-02 15:53 ` Stephen Warren
  2013-08-05  3:34   ` Bard Liao
  0 siblings, 1 reply; 35+ messages in thread
From: Stephen Warren @ 2013-08-02 15:53 UTC (permalink / raw)
  To: bardliao; +Cc: oder_chiou, alsa-devel, swarren, lgirdwood, broonie, flove

On 08/01/2013 08:38 PM, bardliao@realtek.com wrote:
> From: Bard Liao <bardliao@realtek.com>
> 
> Add mute/unmute control in widget event and modify the power on/off sequence to avoid pop noise.

So, this does seem to improve (remove) pop noise on headphones. However,
it also completely prevents speakers from working. Do you know what the
problem is there?

^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH] ASoC: rt5640: change widget sequence for depop
@ 2013-08-02  2:38 bardliao
  2013-08-02 15:53 ` Stephen Warren
  0 siblings, 1 reply; 35+ messages in thread
From: bardliao @ 2013-08-02  2:38 UTC (permalink / raw)
  To: broonie, lgirdwood
  Cc: oder_chiou, alsa-devel, swarren, swarren, bardliao, flove

From: Bard Liao <bardliao@realtek.com>

Add mute/unmute control in widget event and modify the power on/off sequence to avoid pop noise.

Signed-off-by: Bard Liao <bardliao@realtek.com>
---
 sound/soc/codecs/rt5640.c | 387 ++++++++++++++++++++++++++++++++++++++++------
 sound/soc/codecs/rt5640.h |  15 ++
 2 files changed, 352 insertions(+), 50 deletions(-)

diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index 4db7314..3490f38 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -378,21 +378,119 @@ static const SOC_ENUM_SINGLE_DECL(rt5640_if2_adc_enum, RT5640_DIG_INF_DATA,
 static const char * const rt5640_clsd_spk_ratio[] = {"1.66x", "1.83x", "1.94x",
 	"2x", "2.11x", "2.22x", "2.33x", "2.44x", "2.55x", "2.66x", "2.77x"};
 
+static const char * const rt5640_mute_mode[] = {"mute", "unmute"};
+
+static const SOC_ENUM_SINGLE_DECL(rt5640_hp_enum, 0, 0, rt5640_mute_mode);
+static const SOC_ENUM_SINGLE_DECL(rt5640_spo_enum, 0, 0, rt5640_mute_mode);
+
 static const SOC_ENUM_SINGLE_DECL(
 	rt5640_clsd_spk_ratio_enum, RT5640_CLS_D_OUT,
 	RT5640_CLSD_RATIO_SFT, rt5640_clsd_spk_ratio);
 
+static int rt5640_spo_get(struct snd_kcontrol *kcontrol,
+			   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
+
+	ucontrol->value.integer.value[0] = !rt5640->spo_l_mute;
+	ucontrol->value.integer.value[1] = !rt5640->spo_r_mute;
+
+	return 0;
+}
+
+static int rt5640_spo_put(struct snd_kcontrol *kcontrol,
+			   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
+	unsigned int pow;
+
+	pow = snd_soc_read(codec, RT5640_PWR_DIG1) & RT5640_PWR_CLS_D;
+
+	if (ucontrol->value.integer.value[0]) {
+		rt5640->spo_l_mute = false;
+		if (pow)
+			snd_soc_update_bits(codec, RT5640_SPK_VOL,
+				    RT5640_L_MUTE, 0);
+	} else {
+		rt5640->spo_l_mute = true;
+		snd_soc_update_bits(codec, RT5640_SPK_VOL,
+				    RT5640_L_MUTE,
+				    RT5640_L_MUTE);
+	}
+	if (ucontrol->value.integer.value[1]) {
+		rt5640->spo_r_mute = false;
+		if (pow)
+			snd_soc_update_bits(codec, RT5640_SPK_VOL,
+				    RT5640_R_MUTE, 0);
+	} else {
+		rt5640->spo_r_mute = true;
+		snd_soc_update_bits(codec, RT5640_SPK_VOL,
+				    RT5640_R_MUTE,
+				    RT5640_R_MUTE);
+	}
+
+	return 0;
+}
+
+static int rt5640_hp_get(struct snd_kcontrol *kcontrol,
+			   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
+
+	ucontrol->value.integer.value[0] = !rt5640->hp_l_mute;
+	ucontrol->value.integer.value[1] = !rt5640->hp_r_mute;
+
+	return 0;
+}
+
+static int rt5640_hp_put(struct snd_kcontrol *kcontrol,
+			   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
+	unsigned int pow;
+
+	pow = snd_soc_read(codec,  RT5640_PWR_ANLG1);
+
+	if (ucontrol->value.integer.value[0]) {
+		rt5640->hp_l_mute = false;
+		if (pow & RT5640_PWR_HP_L)
+			snd_soc_update_bits(codec, RT5640_HP_VOL,
+				RT5640_L_MUTE, 0);
+	} else {
+		rt5640->hp_l_mute = true;
+		snd_soc_update_bits(codec, RT5640_HP_VOL,
+			RT5640_L_MUTE, RT5640_L_MUTE);
+	}
+	if (ucontrol->value.integer.value[1]) {
+		rt5640->hp_r_mute = false;
+		if (pow & RT5640_PWR_HP_R)
+			snd_soc_update_bits(codec, RT5640_HP_VOL,
+				RT5640_R_MUTE, 0);
+	} else {
+		rt5640->hp_r_mute = true;
+		snd_soc_update_bits(codec, RT5640_HP_VOL,
+			RT5640_R_MUTE, RT5640_R_MUTE);
+	}
+
+
+	return 0;
+}
+
 static const struct snd_kcontrol_new rt5640_snd_controls[] = {
 	/* Speaker Output Volume */
-	SOC_DOUBLE("Speaker Playback Switch", RT5640_SPK_VOL,
-		RT5640_L_MUTE_SFT, RT5640_R_MUTE_SFT, 1, 1),
+	SOC_DOUBLE_EXT("Speaker Playback Switch", SND_SOC_NOPM,
+		0, 1, 1, 0, rt5640_spo_get, rt5640_spo_put),
 	SOC_DOUBLE("Speaker Channel Switch", RT5640_SPK_VOL,
 		RT5640_VOL_L_SFT, RT5640_VOL_R_SFT, 1, 1),
 	SOC_DOUBLE_TLV("Speaker Playback Volume", RT5640_SPK_VOL,
 		RT5640_L_VOL_SFT, RT5640_R_VOL_SFT, 39, 1, out_vol_tlv),
 	/* Headphone Output Volume */
-	SOC_DOUBLE("HP Playback Switch", RT5640_HP_VOL,
-		RT5640_L_MUTE_SFT, RT5640_R_MUTE_SFT, 1, 1),
+	SOC_DOUBLE_EXT("HP Playback Switch", SND_SOC_NOPM,
+		0, 1, 1, 0, rt5640_hp_get, rt5640_hp_put),
 	SOC_DOUBLE("HP Channel Switch", RT5640_HP_VOL,
 		RT5640_VOL_L_SFT, RT5640_VOL_R_SFT, 1, 1),
 	SOC_DOUBLE_TLV("HP Playback Volume", RT5640_HP_VOL,
@@ -868,33 +966,6 @@ static const SOC_ENUM_SINGLE_DECL(
 static const struct snd_kcontrol_new rt5640_sdi_mux =
 	SOC_DAPM_ENUM("SDI select", rt5640_sdi_sel_enum);
 
-static int spk_event(struct snd_soc_dapm_widget *w,
-	struct snd_kcontrol *kcontrol, int event)
-{
-	struct snd_soc_codec *codec = w->codec;
-	struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
-
-	switch (event) {
-	case SND_SOC_DAPM_POST_PMU:
-		regmap_update_bits(rt5640->regmap, RT5640_PWR_DIG1,
-					0x0001, 0x0001);
-		regmap_update_bits(rt5640->regmap, RT5640_PR_BASE + 0x1c,
-					0xf000, 0xf000);
-		break;
-
-	case SND_SOC_DAPM_PRE_PMD:
-		regmap_update_bits(rt5640->regmap, RT5640_PR_BASE + 0x1c,
-					0xf000, 0x0000);
-		regmap_update_bits(rt5640->regmap, RT5640_PWR_DIG1,
-					0x0001, 0x0000);
-		break;
-
-	default:
-		return 0;
-	}
-	return 0;
-}
-
 static int rt5640_set_dmic1_event(struct snd_soc_dapm_widget *w,
 	struct snd_kcontrol *kcontrol, int event)
 {
@@ -943,6 +1014,216 @@ static int rt5640_set_dmic2_event(struct snd_soc_dapm_widget *w,
 	return 0;
 }
 
+static int rt5640_spo_r_event(struct snd_soc_dapm_widget *w,
+			    struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		if (!rt5640->spo_r_mute)
+			snd_soc_update_bits(codec, RT5640_SPK_VOL,
+					    RT5640_R_MUTE, 0);
+		break;
+
+	case SND_SOC_DAPM_PRE_PMD:
+		snd_soc_update_bits(codec, RT5640_SPK_VOL,
+				    RT5640_R_MUTE,
+				    RT5640_R_MUTE);
+		break;
+
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
+static int rt5640_spo_l_event(struct snd_soc_dapm_widget *w,
+			    struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		if (!rt5640->spo_l_mute)
+			snd_soc_update_bits(codec, RT5640_SPK_VOL,
+					    RT5640_L_MUTE, 0);
+		break;
+
+	case SND_SOC_DAPM_PRE_PMD:
+		snd_soc_update_bits(codec, RT5640_SPK_VOL,
+				    RT5640_L_MUTE, RT5640_L_MUTE);
+		break;
+
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
+void hp_amp_power_on(struct snd_soc_codec *codec)
+{
+	struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
+	/* depop parameters */
+	regmap_update_bits(rt5640->regmap, RT5640_PR_BASE +
+		RT5640_CHPUMP_INT_REG1, 0x0700, 0x0200);
+	regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M2,
+			    RT5640_DEPOP_MASK,
+			    RT5640_DEPOP_MAN);
+	regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M1,
+			    RT5640_HP_CP_MASK |
+			    RT5640_HP_SG_MASK |
+			    RT5640_HP_CB_MASK,
+			    RT5640_HP_CP_PU | RT5640_HP_SG_DIS |
+			    RT5640_HP_CB_PU);
+	regmap_write(rt5640->regmap, RT5640_PR_BASE + RT5640_HP_DCC_INT1,
+			   0x9f00);
+	/* headphone amp power on */
+	regmap_update_bits(rt5640->regmap, RT5640_PWR_ANLG1,
+			    RT5640_PWR_FV1 | RT5640_PWR_FV2, 0);
+	regmap_update_bits(rt5640->regmap, RT5640_PWR_ANLG1,
+			    RT5640_PWR_HA,
+			    RT5640_PWR_HA);
+	usleep_range(20000, 25000);
+	regmap_update_bits(rt5640->regmap, RT5640_PWR_ANLG1,
+			    RT5640_PWR_FV1 | RT5640_PWR_FV2,
+			    RT5640_PWR_FV1 | RT5640_PWR_FV2);
+
+	regmap_update_bits(rt5640->regmap, RT5640_CHARGE_PUMP,
+			    RT5640_PM_HP_MASK, RT5640_PM_HP_HV);
+	regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M1,
+			    RT5640_HP_CO_MASK |
+			    RT5640_HP_SG_MASK,
+			    RT5640_HP_CO_EN | RT5640_HP_SG_EN);
+	regmap_update_bits(rt5640->regmap, RT5640_PR_BASE +
+		RT5640_CHPUMP_INT_REG1, 0x0700, 0x0400);
+}
+
+static void rt5640_pmu_depop(struct snd_soc_codec *codec)
+{
+	struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
+	unsigned int val = 0, pow;
+
+	regmap_read(rt5640->regmap,  RT5640_PWR_ANLG1, &pow);
+	if (rt5640->hp_l_mute || !(pow & RT5640_PWR_HP_L))
+		val |= RT5640_L_MUTE;
+	if (rt5640->hp_r_mute || !(pow & RT5640_PWR_HP_R))
+		val |= RT5640_R_MUTE;
+	/* headphone unmute sequence */
+	regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M3,
+			    RT5640_CP_FQ1_MASK | RT5640_CP_FQ2_MASK |
+			    RT5640_CP_FQ3_MASK,
+			    (RT5640_CP_FQ_192_KHZ << RT5640_CP_FQ1_SFT) |
+			    (RT5640_CP_FQ_12_KHZ << RT5640_CP_FQ2_SFT) |
+			    (RT5640_CP_FQ_192_KHZ << RT5640_CP_FQ3_SFT));
+	regmap_write(rt5640->regmap,
+		RT5640_PR_BASE + RT5640_MAMP_INT_REG2, 0xfc00);
+	regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M1,
+			    RT5640_SMT_TRIG_MASK, RT5640_SMT_TRIG_EN);
+	regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M1,
+			    RT5640_RSTN_MASK, RT5640_RSTN_EN);
+	regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M1,
+			    RT5640_RSTN_MASK | RT5640_HP_L_SMT_MASK |
+			    RT5640_HP_R_SMT_MASK,
+			    RT5640_RSTN_DIS | RT5640_HP_L_SMT_EN |
+			    RT5640_HP_R_SMT_EN);
+	regmap_update_bits(rt5640->regmap, RT5640_HP_VOL,
+			    RT5640_L_MUTE | RT5640_R_MUTE, val);
+	usleep_range(40000, 45000);
+	regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M1,
+			    RT5640_HP_SG_MASK | RT5640_HP_L_SMT_MASK |
+			    RT5640_HP_R_SMT_MASK, RT5640_HP_SG_DIS |
+			    RT5640_HP_L_SMT_DIS | RT5640_HP_R_SMT_DIS);
+
+}
+
+static void rt5640_pmd_depop(struct snd_soc_codec *codec)
+{
+	struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
+	/* headphone mute sequence */
+	regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M3,
+			    RT5640_CP_FQ1_MASK | RT5640_CP_FQ2_MASK |
+			    RT5640_CP_FQ3_MASK,
+			    (RT5640_CP_FQ_96_KHZ << RT5640_CP_FQ1_SFT) |
+			    (RT5640_CP_FQ_12_KHZ << RT5640_CP_FQ2_SFT) |
+			    (RT5640_CP_FQ_96_KHZ << RT5640_CP_FQ3_SFT));
+	regmap_write(rt5640->regmap,
+		RT5640_PR_BASE + RT5640_MAMP_INT_REG2, 0xfc00);
+	regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M1,
+			    RT5640_HP_SG_MASK, RT5640_HP_SG_EN);
+	regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M1,
+			    RT5640_RSTP_MASK, RT5640_RSTP_EN);
+	regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M1,
+			    RT5640_RSTP_MASK | RT5640_HP_L_SMT_MASK |
+			    RT5640_HP_R_SMT_MASK, RT5640_RSTP_DIS |
+			    RT5640_HP_L_SMT_EN | RT5640_HP_R_SMT_EN);
+
+	regmap_update_bits(rt5640->regmap, RT5640_HP_VOL,
+			    RT5640_L_MUTE | RT5640_R_MUTE,
+			    RT5640_L_MUTE | RT5640_R_MUTE);
+	usleep_range(40000, 45000);
+
+	regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M1,
+					    RT5640_HP_SG_MASK |
+					    RT5640_HP_L_SMT_MASK |
+					    RT5640_HP_R_SMT_MASK,
+					    RT5640_HP_SG_DIS |
+					    RT5640_HP_L_SMT_DIS |
+					    RT5640_HP_R_SMT_DIS);
+	regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M1,
+					    RT5640_SMT_TRIG_MASK |
+					    RT5640_HP_CD_PD_MASK |
+					    RT5640_HP_CO_MASK |
+					    RT5640_HP_CP_MASK |
+					    RT5640_HP_SG_MASK |
+					    RT5640_HP_CB_MASK,
+					    RT5640_SMT_TRIG_DIS |
+					    RT5640_HP_CD_PD_EN |
+					    RT5640_HP_CO_DIS | RT5640_HP_CP_PD |
+					    RT5640_HP_SG_EN | RT5640_HP_CB_PD);
+}
+
+static int rt5640_hp_event(struct snd_soc_dapm_widget *w,
+			   struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		rt5640_pmu_depop(codec);
+		break;
+
+	case SND_SOC_DAPM_PRE_PMD:
+		rt5640_pmd_depop(codec);
+		break;
+
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
+static int rt5640_hp_power_event(struct snd_soc_dapm_widget *w,
+			   struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		hp_amp_power_on(codec);
+		break;
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
 static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = {
 	SND_SOC_DAPM_SUPPLY("PLL1", RT5640_PWR_ANLG2,
 			RT5640_PWR_PLL_BIT, 0, NULL, 0),
@@ -1132,15 +1413,23 @@ static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = {
 		rt5640_mono_mix, ARRAY_SIZE(rt5640_mono_mix)),
 	SND_SOC_DAPM_SUPPLY("Improve MONO Amp Drv", RT5640_PWR_ANLG1,
 		RT5640_PWR_MA_BIT, 0, NULL, 0),
-	SND_SOC_DAPM_SUPPLY("Improve HP Amp Drv", RT5640_PWR_ANLG1,
-		SND_SOC_NOPM, 0, NULL, 0),
-	SND_SOC_DAPM_PGA("HP L Amp", RT5640_PWR_ANLG1,
+	SND_SOC_DAPM_SUPPLY_S("Improve HP Amp Drv", 1, SND_SOC_NOPM,
+		0, 0, rt5640_hp_power_event, SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_PGA_S("HP Amp", 1, SND_SOC_NOPM, 0, 0,
+		rt5640_hp_event,
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_SUPPLY("HP L Amp", RT5640_PWR_ANLG1,
 		RT5640_PWR_HP_L_BIT, 0, NULL, 0),
-	SND_SOC_DAPM_PGA("HP R Amp", RT5640_PWR_ANLG1,
+	SND_SOC_DAPM_SUPPLY("HP R Amp", RT5640_PWR_ANLG1,
 		RT5640_PWR_HP_R_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_PGA_E("SPO L Amp", SND_SOC_NOPM,
+		0, 0, NULL, 0, rt5640_spo_l_event,
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+	SND_SOC_DAPM_PGA_E("SPO R Amp", SND_SOC_NOPM,
+		0, 0, NULL, 0, rt5640_spo_r_event,
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
 	SND_SOC_DAPM_SUPPLY("Improve SPK Amp Drv", RT5640_PWR_DIG1,
-		SND_SOC_NOPM, 0, spk_event,
-		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+		RT5640_PWR_CLS_D_BIT, 0, NULL, 0),
 	/* Output Lines */
 	SND_SOC_DAPM_OUTPUT("SPOLP"),
 	SND_SOC_DAPM_OUTPUT("SPOLN"),
@@ -1396,13 +1685,15 @@ static const struct snd_soc_dapm_route rt5640_dapm_routes[] = {
 	{"Mono MIX", "OUTVOL L Switch", "OUTVOL L"},
 	{"Mono MIX", "BST1 Switch", "BST1"},
 
-	{"HP L Amp", NULL, "HPO MIX L"},
-	{"HP R Amp", NULL, "HPO MIX R"},
+	{"HP Amp", NULL, "HPO MIX L"},
+	{"HP Amp", NULL, "HPO MIX R"},
 
-	{"SPOLP", NULL, "SPOL MIX"},
-	{"SPOLN", NULL, "SPOL MIX"},
-	{"SPORP", NULL, "SPOR MIX"},
-	{"SPORN", NULL, "SPOR MIX"},
+	{"SPO L Amp", NULL, "SPOL MIX"},
+	{"SPO R Amp", NULL, "SPOR MIX"},
+	{"SPOLP", NULL, "SPO L Amp"},
+	{"SPOLN", NULL, "SPO L Amp"},
+	{"SPORP", NULL, "SPO R Amp"},
+	{"SPORN", NULL, "SPO R Amp"},
 
 	{"SPOLP", NULL, "Improve SPK Amp Drv"},
 	{"SPOLN", NULL, "Improve SPK Amp Drv"},
@@ -1412,7 +1703,9 @@ static const struct snd_soc_dapm_route rt5640_dapm_routes[] = {
 	{"HPOL", NULL, "Improve HP Amp Drv"},
 	{"HPOR", NULL, "Improve HP Amp Drv"},
 
+	{"HPOL", NULL, "HP Amp"},
 	{"HPOL", NULL, "HP L Amp"},
+	{"HPOR", NULL, "HP Amp"},
 	{"HPOR", NULL, "HP R Amp"},
 	{"LOUTL", NULL, "LOUT MIX"},
 	{"LOUTR", NULL, "LOUT MIX"},
@@ -1792,17 +2085,13 @@ static int rt5640_set_bias_level(struct snd_soc_codec *codec,
 				RT5640_PWR_BG | RT5640_PWR_VREF2,
 				RT5640_PWR_VREF1 | RT5640_PWR_MB |
 				RT5640_PWR_BG | RT5640_PWR_VREF2);
-			mdelay(10);
+			usleep_range(15000, 20000);
 			snd_soc_update_bits(codec, RT5640_PWR_ANLG1,
 				RT5640_PWR_FV1 | RT5640_PWR_FV2,
 				RT5640_PWR_FV1 | RT5640_PWR_FV2);
 			regcache_sync(rt5640->regmap);
 			snd_soc_update_bits(codec, RT5640_DUMMY1,
 						0x0301, 0x0301);
-			snd_soc_update_bits(codec, RT5640_DEPOP_M1,
-						0x001d, 0x0019);
-			snd_soc_update_bits(codec, RT5640_DEPOP_M2,
-						0x2000, 0x2000);
 			snd_soc_update_bits(codec, RT5640_MICBIAS,
 						0x0030, 0x0030);
 		}
@@ -1846,8 +2135,6 @@ static int rt5640_probe(struct snd_soc_codec *codec)
 	rt5640_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
 	snd_soc_update_bits(codec, RT5640_DUMMY1, 0x0301, 0x0301);
-	snd_soc_update_bits(codec, RT5640_DEPOP_M1, 0x001d, 0x0019);
-	snd_soc_update_bits(codec, RT5640_DEPOP_M2, 0x2000, 0x2000);
 	snd_soc_update_bits(codec, RT5640_MICBIAS, 0x0030, 0x0030);
 	snd_soc_update_bits(codec, RT5640_DSP_PATH2, 0xfc00, 0x0c00);
 
diff --git a/sound/soc/codecs/rt5640.h b/sound/soc/codecs/rt5640.h
index c48286d..cb6bce9 100644
--- a/sound/soc/codecs/rt5640.h
+++ b/sound/soc/codecs/rt5640.h
@@ -145,6 +145,8 @@
 
 
 /* Index of Codec Private Register definition */
+#define RT5640_CHPUMP_INT_REG1			0x24
+#define RT5640_MAMP_INT_REG2			0x37
 #define RT5640_3D_SPK				0x63
 #define RT5640_WND_1				0x6c
 #define RT5640_WND_2				0x6d
@@ -153,6 +155,7 @@
 #define RT5640_WND_5				0x70
 #define RT5640_WND_8				0x73
 #define RT5640_DIP_SPK_INF			0x75
+#define RT5640_HP_DCC_INT1			0x77
 #define RT5640_EQ_BW_LOP			0xa0
 #define RT5640_EQ_GN_LOP			0xa1
 #define RT5640_EQ_FC_BP1			0xa2
@@ -1201,6 +1204,14 @@
 #define RT5640_CP_FQ2_SFT			4
 #define RT5640_CP_FQ3_MASK			(0x7)
 #define RT5640_CP_FQ3_SFT			0
+#define RT5640_CP_FQ_1_5_KHZ			0
+#define RT5640_CP_FQ_3_KHZ			1
+#define RT5640_CP_FQ_6_KHZ			2
+#define RT5640_CP_FQ_12_KHZ			3
+#define RT5640_CP_FQ_24_KHZ			4
+#define RT5640_CP_FQ_48_KHZ			5
+#define RT5640_CP_FQ_96_KHZ			6
+#define RT5640_CP_FQ_192_KHZ			7
 
 /* HPOUT charge pump (0x91) */
 #define RT5640_OSW_L_MASK			(0x1 << 11)
@@ -2087,6 +2098,10 @@ struct rt5640_priv {
 	int pll_out;
 
 	int dmic_en;
+	bool spo_l_mute;
+	bool spo_r_mute;
+	bool hp_l_mute;
+	bool hp_r_mute;
 };
 
 #endif
-- 
1.8.1.1.439.g50a6b54

^ permalink raw reply related	[flat|nested] 35+ messages in thread

end of thread, other threads:[~2013-08-21 19:55 UTC | newest]

Thread overview: 35+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-08-05  4:19 [PATCH] ASoC: rt5640: change widget sequence for depop bardliao
2013-08-05 14:48 ` Mark Brown
2013-08-05 17:21   ` Lars-Peter Clausen
2013-08-05 17:58     ` Mark Brown
2013-08-06  8:07     ` [PATCH] ASoC: rt5640: change widget sequencefordepop Bard Liao
2013-08-06  8:45       ` Lars-Peter Clausen
2013-08-06  9:13         ` [PATCH] ASoC: rt5640: change widgetsequencefordepop Bard Liao
2013-08-06  9:35           ` Lars-Peter Clausen
2013-08-06 10:07             ` Bard Liao
2013-08-06 10:16               ` Lars-Peter Clausen
2013-08-06 11:04                 ` Bard Liao
2013-08-06 11:31                   ` Lars-Peter Clausen
2013-08-07  1:32                     ` Bard Liao
2013-08-07  5:40                     ` Bard Liao
2013-08-07  7:45                       ` Lars-Peter Clausen
2013-08-07  8:03                         ` Bard Liao
2013-08-07  8:26                           ` Lars-Peter Clausen
2013-08-07  8:31                             ` Bard Liao
2013-08-07  9:36                             ` Mark Brown
2013-08-07 10:47                               ` Lars-Peter Clausen
2013-08-07 13:05                                 ` Mark Brown
2013-08-09  9:05                                 ` Bard Liao
2013-08-09 13:37                                   ` Lars-Peter Clausen
2013-08-09 14:58                                     ` Mark Brown
2013-08-12  7:27                                       ` Bard Liao
2013-08-05 17:17 ` [PATCH] ASoC: rt5640: change widget sequence for depop Stephen Warren
2013-08-05 17:19 ` Lars-Peter Clausen
  -- strict thread matches above, loose matches on Subject: below --
2013-08-19 12:18 bardliao
2013-08-19 17:29 ` Stephen Warren
2013-08-20  2:36   ` Bard Liao
2013-08-20 16:15     ` Stephen Warren
2013-08-21 19:56       ` Lars-Peter Clausen
2013-08-02  2:38 bardliao
2013-08-02 15:53 ` Stephen Warren
2013-08-05  3:34   ` Bard Liao

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.