diff mbox series

ASoC: nau8821: Add DMIC selections.

Message ID 20211228035101.2973294-1-wtli@nuvoton.com
State New
Headers show
Series ASoC: nau8821: Add DMIC selections. | expand

Commit Message

WTLI Dec. 28, 2021, 3:51 a.m. UTC
Add the following two control options:
1. DMIC pin slew rate selection.
2. DMIC clock speed selection.

Signed-off-by: Seven Lee <wtli@nuvoton.com>
---
 sound/soc/codecs/nau8821.c | 79 ++++++++++++++++++++++++++++++++++++++
 sound/soc/codecs/nau8821.h |  6 ++-
 2 files changed, 84 insertions(+), 1 deletion(-)

Comments

Mark Brown Jan. 4, 2022, 2:29 p.m. UTC | #1
On Tue, Jan 04, 2022 at 11:05:59AM +0800, SevenLee wrote:
> Mark Brown 於 2021/12/29 下午 08:45 寫道:

> > The clock speed seems sensible enough to control from userspace since
> > it's going to be a power/performance tradeoff but why also expose the
> > slew rate to userspace - that seems more like something that would come
> > from the board design?

> Because customers need to adjust different DMIC materials by themselves.
> Adjust which slope is the most suitable according to the conditions of
> use, and
> improve electromagnetic interference by setting the slew rate so that
> customers
> can try the best solution.

Sure, but do they need to do this at runtime?  That sounds like tuning
that you do once during system design and never touch again so better
done as a DT property.
diff mbox series

Patch

diff --git a/sound/soc/codecs/nau8821.c b/sound/soc/codecs/nau8821.c
index 2de818377484..52cdbf263e42 100644
--- a/sound/soc/codecs/nau8821.c
+++ b/sound/soc/codecs/nau8821.c
@@ -305,6 +305,66 @@  static int nau8821_biq_coeff_put(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
+static int nau8821_slew_rate_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+	struct nau8821 *nau8821 = snd_soc_component_get_drvdata(component);
+	unsigned int value;
+
+	regmap_read(nau8821->regmap, NAU8821_R13_DMIC_CTRL, &value);
+	nau8821->def_mclk_src = (value & NAU8821_DMIC_SLEW_MASK)
+		>> NAU8821_DMIC_SLEW_SFT;
+	ucontrol->value.bytes.data[0] = nau8821->def_mclk_src;
+
+	return 0;
+}
+
+static int nau8821_slew_rate_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+	struct nau8821 *nau8821 = snd_soc_component_get_drvdata(component);
+
+	nau8821->def_mclk_src = ucontrol->value.integer.value[0];
+
+	regmap_update_bits(component->regmap, NAU8821_R13_DMIC_CTRL,
+		NAU8821_DMIC_SLEW_MASK,
+		nau8821->def_mclk_src << NAU8821_DMIC_SLEW_SFT);
+
+	return 0;
+}
+
+static int nau8821_dmic_clock_speed_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+	struct nau8821 *nau8821 = snd_soc_component_get_drvdata(component);
+	unsigned int value;
+
+	regmap_read(nau8821->regmap, NAU8821_R13_DMIC_CTRL, &value);
+	nau8821->def_dmic_clock = (value & NAU8821_DMIC_SRC_MASK)
+		>> NAU8821_DMIC_SRC_SFT;
+	ucontrol->value.bytes.data[0] = nau8821->def_dmic_clock;
+
+	return 0;
+}
+
+static int nau8821_dmic_clock_speed_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+	struct nau8821 *nau8821 = snd_soc_component_get_drvdata(component);
+
+	nau8821->def_dmic_clock = ucontrol->value.integer.value[0];
+
+	regmap_update_bits(component->regmap, NAU8821_R13_DMIC_CTRL,
+		NAU8821_DMIC_SRC_MASK,
+		nau8821->def_dmic_clock << NAU8821_DMIC_SRC_SFT);
+
+	return 0;
+}
+
 static const char * const nau8821_adc_decimation[] = {
 	"32", "64", "128", "256" };
 
@@ -319,6 +379,20 @@  static const struct soc_enum nau8821_dac_oversampl_enum =
 	SOC_ENUM_SINGLE(NAU8821_R2C_DAC_CTRL1, NAU8821_DAC_OVERSAMPLE_SFT,
 		ARRAY_SIZE(nau8821_dac_oversampl), nau8821_dac_oversampl);
 
+static const char *const dmic_slew_text[] = {"0", "1", "2", "3", "4", "5",
+	"6", "7"};
+
+static const struct soc_enum nau8821_slew_rate_enum =
+		SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(dmic_slew_text),
+		dmic_slew_text);
+
+static const char *const dmic_clock_speed_text[] = {"3.072", "1.536", "0.768",
+	"0.384"};
+
+static const struct soc_enum nau8821_dmic_clock_speed_enum =
+		SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(dmic_clock_speed_text),
+		dmic_clock_speed_text);
+
 static const DECLARE_TLV_DB_MINMAX_MUTE(adc_vol_tlv, -6600, 2400);
 static const DECLARE_TLV_DB_MINMAX_MUTE(sidetone_vol_tlv, -4200, 0);
 static const DECLARE_TLV_DB_MINMAX(hp_vol_tlv, -900, 0);
@@ -350,6 +424,11 @@  static const struct snd_kcontrol_new nau8821_controls[] = {
 		nau8821_biq_coeff_get, nau8821_biq_coeff_put),
 	SOC_SINGLE("ADC Phase Switch", NAU8821_R1B_TDM_CTRL,
 		NAU8821_ADCPHS_SFT, 1, 0),
+	SOC_ENUM_EXT("Slew Rate Selection", nau8821_slew_rate_enum,
+			nau8821_slew_rate_get, nau8821_slew_rate_put),
+	SOC_ENUM_EXT("DMIC Clock Speed Selection",
+		nau8821_dmic_clock_speed_enum, nau8821_dmic_clock_speed_get,
+		nau8821_dmic_clock_speed_put),
 };
 
 static const struct snd_kcontrol_new nau8821_dmic_mode_switch =
diff --git a/sound/soc/codecs/nau8821.h b/sound/soc/codecs/nau8821.h
index a92edfeb9d3a..0ca099fa98bb 100644
--- a/sound/soc/codecs/nau8821.h
+++ b/sound/soc/codecs/nau8821.h
@@ -228,7 +228,7 @@ 
 #define NAU8821_IRQ_INSERT_DIS		0x1
 
 /* DMIC_CTRL (0x13) */
-#define NAU8821_DMIC_DS_SFT	7
+#define NAU8821_DMIC_DS_SFT	11
 #define NAU8821_DMIC_DS_MASK	(0x1 << NAU8821_DMIC_DS_SFT)
 #define NAU8821_DMIC_DS_HIGH	(0x1 << NAU8821_DMIC_DS_SFT)
 #define NAU8821_DMIC_DS_LOW	(0x0 << NAU8821_DMIC_DS_SFT)
@@ -236,6 +236,8 @@ 
 #define NAU8821_DMIC_SRC_MASK	(0x3 << NAU8821_DMIC_SRC_SFT)
 #define NAU8821_CLK_DMIC_SRC	(0x2 << NAU8821_DMIC_SRC_SFT)
 #define NAU8821_DMIC_EN_SFT	0
+#define NAU8821_DMIC_SLEW_SFT	8
+#define NAU8821_DMIC_SLEW_MASK	(0x7 << NAU8821_DMIC_SLEW_SFT)
 
 /* GPIO12_CTRL (0x1a) */
 #define NAU8821_JKDET_PULL_UP	(0x1 << 11) /* 0 - pull down, 1 - pull up */
@@ -525,6 +527,8 @@  struct nau8821 {
 	int jack_eject_debounce;
 	int fs;
 	int dmic_clk_threshold;
+	int def_mclk_src;
+	int def_dmic_clock;
 };
 
 int nau8821_enable_jack_detect(struct snd_soc_component *component,