ASoC: tlv320aic32x4: Model CODEC_CLKIN in CCF
authorAnnaliese McDermond <nh6z@nh6z.net>
Fri, 22 Mar 2019 00:58:46 +0000 (17:58 -0700)
committerMark Brown <broonie@kernel.org>
Mon, 25 Mar 2019 15:53:33 +0000 (15:53 +0000)
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
sound/soc/codecs/tlv320aic32x4.c

index 5e495fc8d93164b7613b5ffba08d9b873bfd7973..cded85009c8c82a02364a066ea9042683e1a1b52 100644 (file)
@@ -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]);
index 7cf8c7cedfe1f44ea30353fed1968c46892901e3..5496e4e080f4af9f964fe1e3d3c9953c61d0cad2 100644 (file)
@@ -735,12 +735,9 @@ static int aic32x4_setup_clocks(struct snd_soc_component *component,
 
        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 */
@@ -987,6 +984,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);
@@ -999,6 +1005,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,