diff mbox series

[03/13] ASoC: tlv320aic32x4: Model CODEC_CLKIN in CCF

Message ID 20190319033756.20616-4-nh6z@nh6z.net (mailing list archive)
State New, archived
Headers show
Series ASoC: tlv320aic32x4: Rework Clock Setting | expand

Commit Message

Annaliese McDermond March 19, 2019, 3:37 a.m. UTC
Model and manage codec clock input as a component in the Core
Clock Framework.  This should allow us to do some more complex
clock management and power control.  Also, some of the
on-board chip clocks can be exposed to the outside, and this
change will make those clocks easier to consume by other
parts of the kernel.

Signed-off-by: Annaliese McDermond <nh6z@nh6z.net>
---
 sound/soc/codecs/tlv320aic32x4-clk.c | 34 ++++++++++++++++++++++++++++
 sound/soc/codecs/tlv320aic32x4.c     | 18 +++++++++++----
 2 files changed, 47 insertions(+), 5 deletions(-)
diff mbox series

Patch

diff --git a/sound/soc/codecs/tlv320aic32x4-clk.c b/sound/soc/codecs/tlv320aic32x4-clk.c
index 9db31ca62b35..e9c4bec795db 100644
--- a/sound/soc/codecs/tlv320aic32x4-clk.c
+++ b/sound/soc/codecs/tlv320aic32x4-clk.c
@@ -265,6 +265,30 @@  static const struct clk_ops aic32x4_pll_ops = {
 	.get_parent = clk_aic32x4_pll_get_parent,
 };
 
+static int clk_aic32x4_codec_clkin_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct clk_aic32x4 *mux = to_clk_aic32x4(hw);
+
+	return regmap_update_bits(mux->regmap,
+		AIC32X4_CLKMUX,
+		AIC32X4_CODEC_CLKIN_MASK, index << AIC32X4_CODEC_CLKIN_SHIFT);
+}
+
+static u8 clk_aic32x4_codec_clkin_get_parent(struct clk_hw *hw)
+{
+	struct clk_aic32x4 *mux = to_clk_aic32x4(hw);
+	unsigned int val;
+
+	regmap_read(mux->regmap, AIC32X4_CLKMUX, &val);
+
+	return (val & AIC32X4_CODEC_CLKIN_MASK) >> AIC32X4_CODEC_CLKIN_SHIFT;
+}
+
+static const struct clk_ops aic32x4_codec_clkin_ops = {
+	.set_parent = clk_aic32x4_codec_clkin_set_parent,
+	.get_parent = clk_aic32x4_codec_clkin_get_parent,
+};
+
 static struct aic32x4_clkdesc aic32x4_clkdesc_array[] = {
 	{
 		.name = "pll",
@@ -274,6 +298,14 @@  static struct aic32x4_clkdesc aic32x4_clkdesc_array[] = {
 		.ops = &aic32x4_pll_ops,
 		.reg = 0,
 	},
+	{
+		.name = "codec_clkin",
+		.parent_names =
+			(const char *[]) { "mclk", "bclk", "gpio", "pll" },
+		.num_parents = 4,
+		.ops = &aic32x4_codec_clkin_ops,
+		.reg = 0,
+	},
 };
 
 static struct clk *aic32x4_register_clk(struct device *dev,
@@ -314,6 +346,8 @@  int aic32x4_register_clocks(struct device *dev, const char *mclk_name)
 	 */
 	aic32x4_clkdesc_array[0].parent_names =
 			(const char* []) { mclk_name, "bclk", "gpio", "din" };
+	aic32x4_clkdesc_array[1].parent_names =
+			(const char *[]) { mclk_name, "bclk", "gpio", "pll" };
 
 	for (i = 0; i < ARRAY_SIZE(aic32x4_clkdesc_array); ++i)
 		aic32x4_register_clk(dev, &aic32x4_clkdesc_array[i]);
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c
index 0e0af3a3cdf9..6b682743cf9b 100644
--- a/sound/soc/codecs/tlv320aic32x4.c
+++ b/sound/soc/codecs/tlv320aic32x4.c
@@ -719,12 +719,9 @@  static int aic32x4_setup_clocks(struct snd_soc_component *component,
 
 	clk_set_rate(clocks[0].clk, sample_rate);
 
-	/* PLL as CODEC_CLKIN */
-	snd_soc_component_update_bits(component, AIC32X4_CLKMUX,
-			AIC32X4_CODEC_CLKIN_MASK,
-			AIC32X4_CODEC_CLKIN_PLL << AIC32X4_CODEC_CLKIN_SHIFT);
 	/* DAC_MOD_CLK as BDIV_CLKIN */
-	snd_soc_component_update_bits(component, AIC32X4_IFACE3, AIC32X4_BDIVCLK_MASK,
+	snd_soc_component_update_bits(component, AIC32X4_IFACE3,
+				AIC32X4_BDIVCLK_MASK,
 				AIC32X4_DACMOD2BCLK << AIC32X4_BDIVCLK_SHIFT);
 
 	/* NDAC divider value */
@@ -971,6 +968,15 @@  static int aic32x4_component_probe(struct snd_soc_component *component)
 {
 	struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
 	u32 tmp_reg;
+	int ret;
+
+	struct clk_bulk_data clocks[] = {
+	    { .id = "codec_clkin" },
+	};
+
+	ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks);
+	if (ret)
+		return ret;
 
 	if (gpio_is_valid(aic32x4->rstn_gpio)) {
 		ndelay(10);
@@ -983,6 +989,8 @@  static int aic32x4_component_probe(struct snd_soc_component *component)
 	if (aic32x4->setup)
 		aic32x4_setup_gpios(component);
 
+	clk_set_parent(clocks[0].clk, clocks[1].clk);
+
 	/* Power platform configuration */
 	if (aic32x4->power_cfg & AIC32X4_PWR_MICBIAS_2075_LDOIN) {
 		snd_soc_component_write(component, AIC32X4_MICBIAS,