diff mbox series

[v2] ASoC: rt711-sdca: add GE selected mode control

Message ID 20240625084303.2273911-1-shumingf@realtek.com (mailing list archive)
State Accepted
Commit 50b8affb5665efa028998ad2c116b1106623409e
Headers show
Series [v2] ASoC: rt711-sdca: add GE selected mode control | expand

Commit Message

Shuming [θŒƒζ›ΈιŠ˜] June 25, 2024, 8:43 a.m. UTC
From: Shuming Fan <shumingf@realtek.com>

The SDCA spec defines a 'selected_mode' control which can override
the 'detected_mode' reported by hardware.
This is useful for platform integration as well as in cases
where the hardware(e.g. 3.5mm jack cable) is not able to accurately detect the jack type.

Signed-off-by: Shuming Fan <shumingf@realtek.com>
---
 sound/soc/codecs/rt711-sdca.c | 72 +++++++++++++++++++++++++++++++++++
 sound/soc/codecs/rt711-sdca.h |  1 +
 2 files changed, 73 insertions(+)

Comments

Liao, Bard June 25, 2024, 11:50 a.m. UTC | #1
> -----Original Message-----
> From: shumingf@realtek.com <shumingf@realtek.com>
> Sent: Tuesday, June 25, 2024 4:43 PM
> To: broonie@kernel.org; lgirdwood@gmail.com
> Cc: linux-sound@vger.kernel.org; lars@metafoo.de; flove@realtek.com;
> oder_chiou@realtek.com; jack.yu@realtek.com; derek.fang@realtek.com;
> Bossart, Pierre-louis <pierre-louis.bossart@intel.com>; Liao, Bard
> <bard.liao@intel.com>; Shuming Fan <shumingf@realtek.com>
> Subject: [PATCH v2] ASoC: rt711-sdca: add GE selected mode control
> 
> From: Shuming Fan <shumingf@realtek.com>
> 
> The SDCA spec defines a 'selected_mode' control which can override
> the 'detected_mode' reported by hardware.
> This is useful for platform integration as well as in cases
> where the hardware(e.g. 3.5mm jack cable) is not able to accurately detect the
> jack type.
> 
> Signed-off-by: Shuming Fan <shumingf@realtek.com>

Tested-by: yung-chuan.liao@linux.intel.com

> ---
>  sound/soc/codecs/rt711-sdca.c | 72
> +++++++++++++++++++++++++++++++++++
>  sound/soc/codecs/rt711-sdca.h |  1 +
>  2 files changed, 73 insertions(+)
> 
> diff --git a/sound/soc/codecs/rt711-sdca.c b/sound/soc/codecs/rt711-sdca.c
> index 1e8dbfc3ecd9..dd6ccf17afd4 100644
> --- a/sound/soc/codecs/rt711-sdca.c
> +++ b/sound/soc/codecs/rt711-sdca.c
> @@ -81,6 +81,24 @@ static void rt711_sdca_reset(struct rt711_sdca_priv
> *rt711)
>  		RT711_HDA_LEGACY_RESET_CTL, 0x1, 0x1);
>  }
> 
> +static void rt711_sdca_ge_force_jack_type(struct rt711_sdca_priv *rt711,
> unsigned int det_mode)
> +{
> +	switch (det_mode) {
> +	case 0x00:
> +		rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG,
> RT711_COMBO_JACK_AUTO_CTL1, 0x8400, 0x0000);
> +		rt711_sdca_index_update_bits(rt711,
> RT711_VENDOR_HDA_CTL, RT711_PUSH_BTN_INT_CTL0, 0x10, 0x00);
> +		break;
> +	case 0x03:
> +		rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG,
> RT711_COMBO_JACK_AUTO_CTL1, 0x8400, 0x8000);
> +		rt711_sdca_index_update_bits(rt711,
> RT711_VENDOR_HDA_CTL, RT711_PUSH_BTN_INT_CTL0, 0x17, 0x13);
> +		break;
> +	case 0x05:
> +		rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG,
> RT711_COMBO_JACK_AUTO_CTL1, 0x8400, 0x8400);
> +		rt711_sdca_index_update_bits(rt711,
> RT711_VENDOR_HDA_CTL, RT711_PUSH_BTN_INT_CTL0, 0x17, 0x15);
> +		break;
> +	}
> +}
> +
>  static int rt711_sdca_calibration(struct rt711_sdca_priv *rt711)
>  {
>  	unsigned int val, loop_rc = 0, loop_dc = 0;
> @@ -248,6 +266,8 @@ static int rt711_sdca_headset_detect(struct
> rt711_sdca_priv *rt711)
>  	unsigned int det_mode;
>  	int ret;
> 
> +	rt711_sdca_ge_force_jack_type(rt711, rt711->ge_mode_override);
> +
>  	/* get detected_mode */
>  	ret = regmap_read(rt711->regmap,
>  		SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC,
> RT711_SDCA_ENT_GE49, RT711_SDCA_CTL_DETECTED_MODE, 0),
> @@ -790,6 +810,56 @@ static int rt711_sdca_fu0f_capture_put(struct
> snd_kcontrol *kcontrol,
>  	return changed;
>  }
> 
> +static int rt711_sdca_ge_select_get(struct snd_kcontrol *kcontrol,
> +			      struct snd_ctl_elem_value *ucontrol)
> +{
> +	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
> +	struct snd_soc_component *component =
> snd_soc_kcontrol_component(kcontrol);
> +	struct rt711_sdca_priv *rt711 =
> snd_soc_component_get_drvdata(component);
> +	unsigned int val, item;
> +
> +	val = (rt711->ge_mode_override >> e->shift_l) & e->mask;
> +	item = snd_soc_enum_val_to_item(e, val);
> +	ucontrol->value.enumerated.item[0] = item;
> +	return 0;
> +}
> +
> +static int rt711_sdca_ge_select_put(struct snd_kcontrol *kcontrol,
> +			      struct snd_ctl_elem_value *ucontrol)
> +{
> +	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
> +	unsigned int *item = ucontrol->value.enumerated.item;
> +	struct snd_soc_component *component =
> snd_soc_kcontrol_component(kcontrol);
> +	struct rt711_sdca_priv *rt711 =
> snd_soc_component_get_drvdata(component);
> +	unsigned int val, change = 0;
> +
> +	if (item[0] >= e->items)
> +		return -EINVAL;
> +
> +	val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l;
> +	if (rt711->ge_mode_override != val) {
> +		rt711->ge_mode_override = val;
> +		change = 1;
> +	}
> +
> +	return change;
> +}
> +
> +static const char * const rt711_sdca_ge_select[] = {
> +	"Auto",
> +	"Headphone",
> +	"Headset",
> +};
> +
> +static int rt711_sdca_ge_select_values[] = {
> +	0,
> +	3,
> +	5,
> +};
> +
> +static SOC_VALUE_ENUM_SINGLE_DECL(rt711_sdca_ge_mode_enum,
> SND_SOC_NOPM,
> +	0, 0x7, rt711_sdca_ge_select, rt711_sdca_ge_select_values);
> +
>  static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -6525, 75, 0);
>  static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -1725, 75, 0);
>  static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0);
> @@ -824,6 +894,8 @@ static const struct snd_kcontrol_new
> rt711_sdca_snd_controls[] = {
>  		SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY,
> RT711_SDCA_ENT_PLATFORM_FU15, RT711_SDCA_CTL_FU_CH_GAIN,
> CH_R),
>  		8, 3, 0,
>  		rt711_sdca_set_gain_get, rt711_sdca_set_gain_put,
> mic_vol_tlv),
> +	SOC_ENUM_EXT("GE49 Selected Mode",
> rt711_sdca_ge_mode_enum,
> +		rt711_sdca_ge_select_get, rt711_sdca_ge_select_put),
>  };
> 
>  static int rt711_sdca_mux_get(struct snd_kcontrol *kcontrol,
> diff --git a/sound/soc/codecs/rt711-sdca.h b/sound/soc/codecs/rt711-
> sdca.h
> index 11d421e8ab2b..15263dcb0314 100644
> --- a/sound/soc/codecs/rt711-sdca.h
> +++ b/sound/soc/codecs/rt711-sdca.h
> @@ -33,6 +33,7 @@ struct  rt711_sdca_priv {
>  	int hw_ver;
>  	bool fu0f_dapm_mute, fu0f_mixer_l_mute, fu0f_mixer_r_mute;
>  	bool fu1e_dapm_mute, fu1e_mixer_l_mute, fu1e_mixer_r_mute;
> +	unsigned int ge_mode_override;
>  };
> 
>  /* NID */
> --
> 2.34.1
Mark Brown June 25, 2024, 8:10 p.m. UTC | #2
On Tue, 25 Jun 2024 16:43:03 +0800, shumingf@realtek.com wrote:
> The SDCA spec defines a 'selected_mode' control which can override
> the 'detected_mode' reported by hardware.
> This is useful for platform integration as well as in cases
> where the hardware(e.g. 3.5mm jack cable) is not able to accurately detect the jack type.
> 
> 

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next

Thanks!

[1/1] ASoC: rt711-sdca: add GE selected mode control
      commit: 50b8affb5665efa028998ad2c116b1106623409e

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark
diff mbox series

Patch

diff --git a/sound/soc/codecs/rt711-sdca.c b/sound/soc/codecs/rt711-sdca.c
index 1e8dbfc3ecd9..dd6ccf17afd4 100644
--- a/sound/soc/codecs/rt711-sdca.c
+++ b/sound/soc/codecs/rt711-sdca.c
@@ -81,6 +81,24 @@  static void rt711_sdca_reset(struct rt711_sdca_priv *rt711)
 		RT711_HDA_LEGACY_RESET_CTL, 0x1, 0x1);
 }
 
+static void rt711_sdca_ge_force_jack_type(struct rt711_sdca_priv *rt711, unsigned int det_mode)
+{
+	switch (det_mode) {
+	case 0x00:
+		rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, RT711_COMBO_JACK_AUTO_CTL1, 0x8400, 0x0000);
+		rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, RT711_PUSH_BTN_INT_CTL0, 0x10, 0x00);
+		break;
+	case 0x03:
+		rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, RT711_COMBO_JACK_AUTO_CTL1, 0x8400, 0x8000);
+		rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, RT711_PUSH_BTN_INT_CTL0, 0x17, 0x13);
+		break;
+	case 0x05:
+		rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, RT711_COMBO_JACK_AUTO_CTL1, 0x8400, 0x8400);
+		rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, RT711_PUSH_BTN_INT_CTL0, 0x17, 0x15);
+		break;
+	}
+}
+
 static int rt711_sdca_calibration(struct rt711_sdca_priv *rt711)
 {
 	unsigned int val, loop_rc = 0, loop_dc = 0;
@@ -248,6 +266,8 @@  static int rt711_sdca_headset_detect(struct rt711_sdca_priv *rt711)
 	unsigned int det_mode;
 	int ret;
 
+	rt711_sdca_ge_force_jack_type(rt711, rt711->ge_mode_override);
+
 	/* get detected_mode */
 	ret = regmap_read(rt711->regmap,
 		SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_GE49, RT711_SDCA_CTL_DETECTED_MODE, 0),
@@ -790,6 +810,56 @@  static int rt711_sdca_fu0f_capture_put(struct snd_kcontrol *kcontrol,
 	return changed;
 }
 
+static int rt711_sdca_ge_select_get(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+	struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component);
+	unsigned int val, item;
+
+	val = (rt711->ge_mode_override >> e->shift_l) & e->mask;
+	item = snd_soc_enum_val_to_item(e, val);
+	ucontrol->value.enumerated.item[0] = item;
+	return 0;
+}
+
+static int rt711_sdca_ge_select_put(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+	unsigned int *item = ucontrol->value.enumerated.item;
+	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+	struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component);
+	unsigned int val, change = 0;
+
+	if (item[0] >= e->items)
+		return -EINVAL;
+
+	val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l;
+	if (rt711->ge_mode_override != val) {
+		rt711->ge_mode_override = val;
+		change = 1;
+	}
+
+	return change;
+}
+
+static const char * const rt711_sdca_ge_select[] = {
+	"Auto",
+	"Headphone",
+	"Headset",
+};
+
+static int rt711_sdca_ge_select_values[] = {
+	0,
+	3,
+	5,
+};
+
+static SOC_VALUE_ENUM_SINGLE_DECL(rt711_sdca_ge_mode_enum, SND_SOC_NOPM,
+	0, 0x7, rt711_sdca_ge_select, rt711_sdca_ge_select_values);
+
 static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -6525, 75, 0);
 static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -1725, 75, 0);
 static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0);
@@ -824,6 +894,8 @@  static const struct snd_kcontrol_new rt711_sdca_snd_controls[] = {
 		SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_PLATFORM_FU15, RT711_SDCA_CTL_FU_CH_GAIN, CH_R),
 		8, 3, 0,
 		rt711_sdca_set_gain_get, rt711_sdca_set_gain_put, mic_vol_tlv),
+	SOC_ENUM_EXT("GE49 Selected Mode", rt711_sdca_ge_mode_enum,
+		rt711_sdca_ge_select_get, rt711_sdca_ge_select_put),
 };
 
 static int rt711_sdca_mux_get(struct snd_kcontrol *kcontrol,
diff --git a/sound/soc/codecs/rt711-sdca.h b/sound/soc/codecs/rt711-sdca.h
index 11d421e8ab2b..15263dcb0314 100644
--- a/sound/soc/codecs/rt711-sdca.h
+++ b/sound/soc/codecs/rt711-sdca.h
@@ -33,6 +33,7 @@  struct  rt711_sdca_priv {
 	int hw_ver;
 	bool fu0f_dapm_mute, fu0f_mixer_l_mute, fu0f_mixer_r_mute;
 	bool fu1e_dapm_mute, fu1e_mixer_l_mute, fu1e_mixer_r_mute;
+	unsigned int ge_mode_override;
 };
 
 /* NID */