Commit fd2df3ae authored by Annaliese McDermond's avatar Annaliese McDermond Committed by Mark Brown

ASoC: tlv320aic32x4: Model CODEC_CLKIN in CCF

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: default avatarAnnaliese McDermond <nh6z@nh6z.net>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 514b044c
...@@ -265,6 +265,30 @@ static const struct clk_ops aic32x4_pll_ops = { ...@@ -265,6 +265,30 @@ static const struct clk_ops aic32x4_pll_ops = {
.get_parent = clk_aic32x4_pll_get_parent, .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[] = { static struct aic32x4_clkdesc aic32x4_clkdesc_array[] = {
{ {
.name = "pll", .name = "pll",
...@@ -274,6 +298,14 @@ static struct aic32x4_clkdesc aic32x4_clkdesc_array[] = { ...@@ -274,6 +298,14 @@ static struct aic32x4_clkdesc aic32x4_clkdesc_array[] = {
.ops = &aic32x4_pll_ops, .ops = &aic32x4_pll_ops,
.reg = 0, .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, static struct clk *aic32x4_register_clk(struct device *dev,
...@@ -314,6 +346,8 @@ int aic32x4_register_clocks(struct device *dev, const char *mclk_name) ...@@ -314,6 +346,8 @@ int aic32x4_register_clocks(struct device *dev, const char *mclk_name)
*/ */
aic32x4_clkdesc_array[0].parent_names = aic32x4_clkdesc_array[0].parent_names =
(const char* []) { mclk_name, "bclk", "gpio", "din" }; (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) for (i = 0; i < ARRAY_SIZE(aic32x4_clkdesc_array); ++i)
aic32x4_register_clk(dev, &aic32x4_clkdesc_array[i]); aic32x4_register_clk(dev, &aic32x4_clkdesc_array[i]);
......
...@@ -735,12 +735,9 @@ static int aic32x4_setup_clocks(struct snd_soc_component *component, ...@@ -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); 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 */ /* 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); AIC32X4_DACMOD2BCLK << AIC32X4_BDIVCLK_SHIFT);
/* NDAC divider value */ /* NDAC divider value */
...@@ -987,6 +984,15 @@ static int aic32x4_component_probe(struct snd_soc_component *component) ...@@ -987,6 +984,15 @@ static int aic32x4_component_probe(struct snd_soc_component *component)
{ {
struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component); struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
u32 tmp_reg; 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)) { if (gpio_is_valid(aic32x4->rstn_gpio)) {
ndelay(10); ndelay(10);
...@@ -999,6 +1005,8 @@ static int aic32x4_component_probe(struct snd_soc_component *component) ...@@ -999,6 +1005,8 @@ static int aic32x4_component_probe(struct snd_soc_component *component)
if (aic32x4->setup) if (aic32x4->setup)
aic32x4_setup_gpios(component); aic32x4_setup_gpios(component);
clk_set_parent(clocks[0].clk, clocks[1].clk);
/* Power platform configuration */ /* Power platform configuration */
if (aic32x4->power_cfg & AIC32X4_PWR_MICBIAS_2075_LDOIN) { if (aic32x4->power_cfg & AIC32X4_PWR_MICBIAS_2075_LDOIN) {
snd_soc_component_write(component, AIC32X4_MICBIAS, snd_soc_component_write(component, AIC32X4_MICBIAS,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment