2019-09-19 14:43:19 +00:00
|
|
|
From c5f9d78ec34de15732bcbff52bedba7a840e42b2 Mon Sep 17 00:00:00 2001
|
2019-07-09 18:32:28 +00:00
|
|
|
From: Annaliese McDermond <nh6z@nh6z.net>
|
|
|
|
Date: Thu, 21 Mar 2019 17:58:46 -0700
|
2019-12-23 12:42:55 +00:00
|
|
|
Subject: [PATCH] ASoC: tlv320aic32x4: Model CODEC_CLKIN in CCF
|
2019-07-09 18:32:28 +00:00
|
|
|
|
|
|
|
commit fd2df3aeafa4b4cc468d58e147e0822967034b71 upstream.
|
|
|
|
|
|
|
|
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>
|
|
|
|
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
|
|
---
|
|
|
|
sound/soc/codecs/tlv320aic32x4-clk.c | 34 ++++++++++++++++++++++++++++
|
|
|
|
sound/soc/codecs/tlv320aic32x4.c | 18 +++++++++++----
|
|
|
|
2 files changed, 47 insertions(+), 5 deletions(-)
|
|
|
|
|
|
|
|
--- 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_
|
|
|
|
.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_cl
|
|
|
|
.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 devic
|
|
|
|
*/
|
|
|
|
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]);
|
|
|
|
--- a/sound/soc/codecs/tlv320aic32x4.c
|
|
|
|
+++ b/sound/soc/codecs/tlv320aic32x4.c
|
|
|
|
@@ -737,12 +737,9 @@ static int aic32x4_setup_clocks(struct s
|
|
|
|
|
|
|
|
aic32x4_set_processing_blocks(component, aic32x4_divs[i].r_block, aic32x4_divs[i].p_block);
|
|
|
|
|
|
|
|
- /* 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 */
|
|
|
|
@@ -989,6 +986,15 @@ static int aic32x4_component_probe(struc
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
@@ -1000,6 +1006,8 @@ static int aic32x4_component_probe(struc
|
|
|
|
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,
|