From 18c581a03ea7aedfa15a330d748ff934967be3ce Mon Sep 17 00:00:00 2001 From: Sameer Pujar Date: Sun, 28 Jul 2019 10:40:50 +0530 Subject: [PATCH] ASoC: tegra-alt: clock cleanup for machine driver Highlights from current clock handling in machine driver(L4T/Android) * Tegra210 and Tegra186/194 have different approaches to update clock rates for pll_a, pll_a_out0, mclk and ahub. -> Tegra210 uses static method, where base pll_a rate is hardcoded in the driver. -> Tegra186/194 use DT driven approach, where sound node passes rates for above clocks. Two sets of rates are passed, one to support odd sample rates and one for even. * Some of the functions from tegra_asoc_utils_alt.c are unused * clock names are not really generic. This patch has following updates. * Unify clock update approach. Use static array for base pll rates. This also helps to get rid of following sound node DT properties. "nvidia,num-rates" "nvidia,clk-rates" * Remove below unused functions. tegra_alt_asoc_utils_lock_clk_rate() tegra_alt_asoc_utils_register_ctls() tegra_alt_asoc_utils_tristate_dap() * clk_set_parent() functions are not needed. Instead the relationship can be set from DT through "assigned-clocks" binding. * update clock handle names to be more meaningful. However, clock names that are parsed in devm_clk_get() are not changed because these names are used in Automotive DT files under "sound_ref" node. Scope of current patch is limited to L4T/Android drivers and DT files. Bug 200503387 Bug 200516191 Change-Id: Ideaf150e6e200ffbba4dcbdec4c49f1127ea25db Signed-off-by: Sameer Pujar Reviewed-on: https://git-master.nvidia.com/r/2164482 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Ravindra Lokhande Reviewed-by: Mohan Kumar D Reviewed-by: Sharad Gupta Reviewed-by: mobile promotions Tested-by: mobile promotions --- .../soc/tegra-alt/include/tegra210_xbar_alt.h | 1 - .../include/tegra_asoc_machine_alt.h | 4 +- .../tegra-alt/include/tegra_asoc_utils_alt.h | 43 ++-- .../tegra_machine_driver_mobile.c | 139 ++++-------- .../tegra-alt/utils/tegra210_xbar_utils_alt.c | 16 -- .../tegra-alt/utils/tegra_asoc_utils_alt.c | 206 ++++++++---------- 6 files changed, 144 insertions(+), 265 deletions(-) diff --git a/sound/soc/tegra-alt/include/tegra210_xbar_alt.h b/sound/soc/tegra-alt/include/tegra210_xbar_alt.h index e87d9c1b..fb609eaf 100644 --- a/sound/soc/tegra-alt/include/tegra210_xbar_alt.h +++ b/sound/soc/tegra-alt/include/tegra210_xbar_alt.h @@ -205,7 +205,6 @@ struct tegra_soc_bytes { u32 shift; /* Used as offset for ahub ram related programing */ }; -int tegra210_xbar_set_clock(unsigned long rate); void tegra210_xbar_set_cif(struct regmap *regmap, unsigned int reg, struct tegra210_xbar_cif_conf *conf); void tegra210_xbar_write_ahubram(struct regmap *regmap, unsigned int reg_ctrl, diff --git a/sound/soc/tegra-alt/include/tegra_asoc_machine_alt.h b/sound/soc/tegra-alt/include/tegra_asoc_machine_alt.h index c7fce890..8fd4a681 100644 --- a/sound/soc/tegra-alt/include/tegra_asoc_machine_alt.h +++ b/sound/soc/tegra-alt/include/tegra_asoc_machine_alt.h @@ -34,9 +34,7 @@ struct tegra_machine_soc_data { sfc_dai_link; bool is_asrc_available, - is_clk_rate_via_dt, - write_cdev1_state, - write_idle_bias_off_state; + write_idle_bias_off_state; struct snd_soc_codec_conf *ahub_confs; struct snd_soc_dai_link *ahub_links; diff --git a/sound/soc/tegra-alt/include/tegra_asoc_utils_alt.h b/sound/soc/tegra-alt/include/tegra_asoc_utils_alt.h index 0517a02f..c5ddc754 100644 --- a/sound/soc/tegra-alt/include/tegra_asoc_utils_alt.h +++ b/sound/soc/tegra-alt/include/tegra_asoc_utils_alt.h @@ -2,7 +2,7 @@ * tegra_alt_asoc_utils.h - Definitions for MCLK and DAP Utility driver * * Author: Stephen Warren - * Copyright (c) 2011-2019 NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2011-2019 NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -32,7 +32,10 @@ enum tegra_asoc_utils_soc { TEGRA_ASOC_UTILS_SOC_TEGRA194, }; -/* Maintain same order in DT entry */ +/* + * Maintain same order in DT entry + * FIXME: (This would be removed going ahead) + */ enum tegra_asoc_utils_clkrate { PLLA_x11025_RATE, AUD_MCLK_x11025_RATE, @@ -49,36 +52,30 @@ struct tegra_asoc_audio_clock_info { struct device *dev; struct snd_soc_card *card; enum tegra_asoc_utils_soc soc; - struct clk *clk_pll_a; - struct clk *clk_pll_a_out0; - struct clk *clk_cdev1; + struct clk *clk_pll_base; + struct clk *clk_pll_out; + struct clk *clk_aud_mclk; struct clk *clk_ahub; struct reset_control *clk_cdev1_rst; - struct clk *clk_pll_p_out1; - int set_mclk; - int lock_count; - int set_baseclock; - int num_clk; - struct clk *clk_mclk_parent; - u32 set_clk_out_rate; - u32 mclk_rate; + unsigned int *pll_base_rate; + u32 set_pll_base_rate; + u32 set_pll_out_rate; + u32 set_aud_mclk_rate; u32 mclk_scale; + /* fixed MCLK rate from DT */ + u32 mclk_rate; + + /* FIXME: below would be removed going ahead */ u32 clk_rates[MAX_NUM_RATES]; + u32 num_clk; }; int tegra_alt_asoc_utils_set_rate(struct tegra_asoc_audio_clock_info *data, - int srate, - int mclk, - u32 clk_out_rate); -void tegra_alt_asoc_utils_lock_clk_rate( - struct tegra_asoc_audio_clock_info *data, - int lock); + unsigned int srate, unsigned int mclk, + unsigned int clk_out_rate); int tegra_alt_asoc_utils_init(struct tegra_asoc_audio_clock_info *data, - struct device *dev, struct snd_soc_card *card); + struct device *dev, struct snd_soc_card *card); int tegra_alt_asoc_utils_clk_enable(struct tegra_asoc_audio_clock_info *data); int tegra_alt_asoc_utils_clk_disable(struct tegra_asoc_audio_clock_info *data); -int tegra_alt_asoc_utils_register_ctls(struct tegra_asoc_audio_clock_info *data); - -int tegra_alt_asoc_utils_tristate_dap(int id, bool tristate); #endif diff --git a/sound/soc/tegra-alt/machine_drivers/tegra_machine_driver_mobile.c b/sound/soc/tegra-alt/machine_drivers/tegra_machine_driver_mobile.c index 95543ff8..efe40550 100644 --- a/sound/soc/tegra-alt/machine_drivers/tegra_machine_driver_mobile.c +++ b/sound/soc/tegra-alt/machine_drivers/tegra_machine_driver_mobile.c @@ -70,9 +70,9 @@ static int tegra_machine_suspend_pre(struct snd_soc_card *); static int tegra_machine_pcm_hw_params(struct snd_pcm_substream *, struct snd_pcm_hw_params *); static int tegra_machine_dai_init(struct snd_soc_pcm_runtime *, - int, int, u64, bool); + unsigned int, unsigned int, u64, bool); static int tegra_machine_set_params(struct snd_soc_card *, - struct tegra_machine *, int, int, u64); + struct tegra_machine *, unsigned int, unsigned int, u64); static int tegra_machine_codec_get_rate(struct snd_kcontrol *, struct snd_ctl_elem_value *); static int tegra_machine_codec_put_rate(struct snd_kcontrol *, @@ -94,7 +94,6 @@ static const struct tegra_machine_soc_data soc_data_tegra210 = { #endif .sfc_dai_link = TEGRA210_DAI_LINK_SFC1_RX, - .is_clk_rate_via_dt = false, .write_idle_bias_off_state = false, .ahub_links = tegra210_xbar_dai_links, @@ -115,7 +114,6 @@ static const struct tegra_machine_soc_data soc_data_tegra186 = { #endif .sfc_dai_link = TEGRA186_DAI_LINK_SFC1_RX, - .is_clk_rate_via_dt = true, .write_idle_bias_off_state = true, .ahub_links = tegra186_xbar_dai_links, @@ -293,10 +291,10 @@ static int tegra_machine_codec_put_format(struct snd_kcontrol *kcontrol, } static int tegra_machine_set_params(struct snd_soc_card *card, - struct tegra_machine *machine, - int rate, - int channels, - u64 formats) + struct tegra_machine *machine, + unsigned int rate, + unsigned int channels, + u64 formats) { unsigned int mask = (1 << channels) - 1; int idx = 0, err = 0; @@ -352,72 +350,31 @@ static int tegra_machine_set_params(struct snd_soc_card *card, return 0; } static int tegra_machine_dai_init(struct snd_soc_pcm_runtime *runtime, - int rate, - int channels, - u64 formats, - bool is_playback) + unsigned int rate, unsigned int channels, + u64 formats, bool is_playback) { struct snd_soc_card *card = runtime->card; struct tegra_machine *machine = snd_soc_card_get_drvdata(card); struct snd_soc_pcm_stream *dai_params; - unsigned int clk_out_rate = 0, mclk = 0; - int err, codec_rate, clk_rate; + unsigned int aud_mclk, srate; + int err; struct snd_soc_pcm_runtime *rtd; - codec_rate = tegra_machine_srate_values[machine->rate_via_kcontrol]; - clk_rate = (machine->rate_via_kcontrol) ? codec_rate : rate; + srate = (machine->rate_via_kcontrol) ? + tegra_machine_srate_values[machine->rate_via_kcontrol] : + rate; - if (!machine->soc_data->is_clk_rate_via_dt) { - /* TODO remove this hardcoding */ - /* aud_mclk, 256 times the sample rate */ - clk_out_rate = clk_rate << 8; - switch (clk_rate) { - case 11025: - mclk = 22579200; - break; - case 22050: - case 44100: - case 88200: - case 176400: - mclk = 45158400; - break; - case 8000: - mclk = 24576000; - break; - case 16000: - case 32000: - case 48000: - case 64000: - case 96000: - case 192000: - default: - mclk = 49152000; - break; - } - - err = tegra210_xbar_set_clock(mclk); - if (err < 0) { - dev_err(card->dev, - "Can't configure xbar clock = %d Hz\n", mclk); - return err; - } - } - - err = tegra_alt_asoc_utils_set_rate(&machine->audio_clock, clk_rate, - mclk, clk_out_rate); + err = tegra_alt_asoc_utils_set_rate(&machine->audio_clock, srate, 0, 0); if (err < 0) { dev_err(card->dev, "Can't configure clocks\n"); return err; } - if (machine->soc_data->is_clk_rate_via_dt) - clk_out_rate = machine->audio_clock.set_clk_out_rate; + aud_mclk = machine->audio_clock.set_aud_mclk_rate; - pr_debug("pll_a_out0 = %d Hz, aud_mclk = %d Hz, codec rate = %d Hz\n", - machine->audio_clock.set_mclk, - machine->audio_clock.set_clk_out_rate, clk_rate); + pr_debug("pll_a_out0 = %u Hz, aud_mclk = %u Hz, sample rate = %u Hz\n", + machine->audio_clock.set_pll_out_rate, aud_mclk, srate); - /* TODO: should we pass here clk_rate ? */ err = tegra_machine_set_params(card, machine, rate, channels, formats); if (err < 0) return err; @@ -427,12 +384,12 @@ static int tegra_machine_dai_init(struct snd_soc_pcm_runtime *runtime, dai_params = (struct snd_soc_pcm_stream *)rtd->dai_link->params; - dai_params->rate_min = clk_rate; + dai_params->rate_min = srate; dai_params->formats = (machine->fmt_via_kcontrol == 2) ? (1ULL << SNDRV_PCM_FORMAT_S32_LE) : formats; err = snd_soc_dai_set_sysclk(rtd->codec_dai, RT5659_SCLK_S_MCLK, - clk_out_rate, SND_SOC_CLOCK_IN); + aud_mclk, SND_SOC_CLOCK_IN); if (err < 0) { dev_err(card->dev, "codec_dai clock not set\n"); return err; @@ -446,22 +403,22 @@ static int tegra_machine_dai_init(struct snd_soc_pcm_runtime *runtime, dai_params = (struct snd_soc_pcm_stream *)rtd->dai_link->params; - dai_params->rate_min = clk_rate; + dai_params->rate_min = srate; dai_params->formats = (machine->fmt_via_kcontrol == 2) ? (1ULL << SNDRV_PCM_FORMAT_S32_LE) : formats; switch (dai_params->formats) { case SNDRV_PCM_FMTBIT_S8: - bclk_rate = clk_rate * channels * 8; + bclk_rate = srate * channels * 8; break; case SNDRV_PCM_FMTBIT_S16_LE: - bclk_rate = clk_rate * channels * 16; + bclk_rate = srate * channels * 16; break; case SNDRV_PCM_FMTBIT_S24_LE: - bclk_rate = clk_rate * channels * 24; + bclk_rate = srate * channels * 24; break; case SNDRV_PCM_FMTBIT_S32_LE: - bclk_rate = clk_rate * channels * 32; + bclk_rate = srate * channels * 32; break; default: dev_err(card->dev, "invalid format %llu\n", @@ -471,29 +428,26 @@ static int tegra_machine_dai_init(struct snd_soc_pcm_runtime *runtime, err = snd_soc_dai_set_pll(rtd->codec_dai, 0, RT5659_PLL1_S_BCLK1, - bclk_rate, clk_rate * 256); + bclk_rate, srate * 256); if (err < 0) { dev_err(card->dev, "failed to set codec pll\n"); return err; } err = snd_soc_dai_set_sysclk(rtd->codec_dai, RT5659_SCLK_S_PLL1, - clk_rate * 256, SND_SOC_CLOCK_IN); + srate * 256, SND_SOC_CLOCK_IN); if (err < 0) { dev_err(card->dev, "codec_dai clock not set\n"); return err; } } - /* TODO: remove below spdif links if clk_rate is passed - * in tegra_machine_set_params - */ rtd = snd_soc_get_pcm_runtime(card, "spdif-dit-0"); if (rtd) { dai_params = (struct snd_soc_pcm_stream *)rtd->dai_link->params; - dai_params->rate_min = clk_rate; + dai_params->rate_min = srate; } rtd = snd_soc_get_pcm_runtime(card, "spdif-dit-1"); @@ -501,7 +455,7 @@ static int tegra_machine_dai_init(struct snd_soc_pcm_runtime *runtime, dai_params = (struct snd_soc_pcm_stream *)rtd->dai_link->params; - dai_params->rate_min = clk_rate; + dai_params->rate_min = srate; } /* set clk rate for i2s3 dai link*/ @@ -510,7 +464,7 @@ static int tegra_machine_dai_init(struct snd_soc_pcm_runtime *runtime, dai_params = (struct snd_soc_pcm_stream *)rtd->dai_link->params; - dai_params->rate_min = clk_rate; + dai_params->rate_min = srate; } rtd = snd_soc_get_pcm_runtime(card, "spdif-dit-3"); @@ -518,7 +472,7 @@ static int tegra_machine_dai_init(struct snd_soc_pcm_runtime *runtime, dai_params = (struct snd_soc_pcm_stream *)rtd->dai_link->params; - dai_params->rate_min = clk_rate; + dai_params->rate_min = srate; } rtd = snd_soc_get_pcm_runtime(card, "spdif-dit-5"); @@ -527,7 +481,7 @@ static int tegra_machine_dai_init(struct snd_soc_pcm_runtime *runtime, (struct snd_soc_pcm_stream *)rtd->dai_link->params; /* update link_param to update hw_param for DAPM */ - dai_params->rate_min = clk_rate; + dai_params->rate_min = srate; dai_params->channels_min = channels; dai_params->formats = formats; } @@ -539,7 +493,7 @@ static int tegra_machine_dai_init(struct snd_soc_pcm_runtime *runtime, if (!strcmp(rtd->codec_dai->name, "tas2552-amplifier")) { err = snd_soc_dai_set_sysclk(rtd->codec_dai, - TAS2552_PDM_CLK_IVCLKIN, clk_out_rate, + TAS2552_PDM_CLK_IVCLKIN, aud_mclk, SND_SOC_CLOCK_IN); if (err < 0) { dev_err(card->dev, "codec_dai clock not set\n"); @@ -555,7 +509,7 @@ static int tegra_machine_dai_init(struct snd_soc_pcm_runtime *runtime, if (!strcmp(rtd->codec_dai->name, "tas2552-amplifier")) { err = snd_soc_dai_set_sysclk(rtd->codec_dai, - TAS2552_PDM_CLK_IVCLKIN, clk_out_rate, + TAS2552_PDM_CLK_IVCLKIN, aud_mclk, SND_SOC_CLOCK_IN); if (err < 0) { dev_err(card->dev, "codec_dai clock not set\n"); @@ -569,7 +523,7 @@ static int tegra_machine_dai_init(struct snd_soc_pcm_runtime *runtime, dai_params = (struct snd_soc_pcm_stream *)rtd->dai_link->params; - dai_params->rate_min = clk_rate; + dai_params->rate_min = srate; dai_params->channels_min = channels; dai_params->formats = formats; } @@ -888,35 +842,18 @@ static int tegra_machine_driver_probe(struct platform_device *pdev) if (ret) return ret; + memset(&machine->audio_clock, 0, sizeof(machine->audio_clock)); if (of_property_read_u32(np, "nvidia,mclk-rate", - &machine->audio_clock.mclk_rate) < 0) + &machine->audio_clock.mclk_rate) < 0) dev_dbg(&pdev->dev, "Missing property nvidia,mclk-rate\n"); if (of_property_read_u32(np, "mclk-fs", - &machine->audio_clock.mclk_scale) < 0) { + &machine->audio_clock.mclk_scale) < 0) { + /* TODO: fix clock in DT and remove usage of default scale */ machine->audio_clock.mclk_scale = 256; dev_dbg(&pdev->dev, "Missing property mclk-fs\n"); } - if (machine->soc_data->is_clk_rate_via_dt) { - ret = of_property_read_u32(np, "nvidia,num-clk", - &machine->audio_clock.num_clk); - if (ret < 0) { - dev_err(&pdev->dev, - "Missing property 'nvidia,num-clk'\n"); - return ret; - } - - ret = of_property_read_u32_array(np, "nvidia,clk-rates", - (u32 *)&machine->audio_clock.clk_rates, - machine->audio_clock.num_clk); - if (ret < 0) { - dev_err(&pdev->dev, - "Missing property 'nvidia,clk-rates'\n"); - return ret; - } - } - tegra_machine_dma_set_mask(pdev); ret = add_dai_links(pdev); diff --git a/sound/soc/tegra-alt/utils/tegra210_xbar_utils_alt.c b/sound/soc/tegra-alt/utils/tegra210_xbar_utils_alt.c index 2d72e8a3..66da7570 100644 --- a/sound/soc/tegra-alt/utils/tegra210_xbar_utils_alt.c +++ b/sound/soc/tegra-alt/utils/tegra210_xbar_utils_alt.c @@ -32,22 +32,6 @@ static struct tegra_xbar *xbar; -int tegra210_xbar_set_clock(unsigned long rate) -{ - int ret = 0; - - ret = clk_set_rate(xbar->clk_parent, rate); - if (ret) - pr_info("Failed to set clock rate of pll_a_out0\n"); - - ret = clk_set_rate(xbar->clk, rate); - if (ret) - pr_info("Failed to set clock rate of ahub\n"); - - return 0; -} -EXPORT_SYMBOL_GPL(tegra210_xbar_set_clock); - void tegra210_xbar_set_cif(struct regmap *regmap, unsigned int reg, struct tegra210_xbar_cif_conf *conf) { diff --git a/sound/soc/tegra-alt/utils/tegra_asoc_utils_alt.c b/sound/soc/tegra-alt/utils/tegra_asoc_utils_alt.c index a57369de..0aa72a05 100644 --- a/sound/soc/tegra-alt/utils/tegra_asoc_utils_alt.c +++ b/sound/soc/tegra-alt/utils/tegra_asoc_utils_alt.c @@ -26,25 +26,37 @@ #include #include #include - #include #include #include - -#include -#include -#include - #include "tegra_asoc_utils_alt.h" +enum rate_type { + ODD_RATE, + EVEN_RATE, + NUM_RATE_TYPE, +}; + +unsigned int tegra210_pll_base_rate[NUM_RATE_TYPE] = { + 338688000, + 368640000, +}; + +unsigned int tegra186_pll_base_rate[NUM_RATE_TYPE] = { + 270950400, + 245760000, +}; + +unsigned int default_pll_out_rate[NUM_RATE_TYPE] = { + 45158400, + 49152000, +}; + int tegra_alt_asoc_utils_set_rate(struct tegra_asoc_audio_clock_info *data, - int srate, - int mclk, - u32 clk_out_rate) + unsigned int srate, unsigned int pll_out, + unsigned int aud_mclk) { - int new_baseclock; - int ahub_rate = 0; - bool clk_change; + unsigned int new_pll_base; int err; switch (srate) { @@ -53,22 +65,8 @@ int tegra_alt_asoc_utils_set_rate(struct tegra_asoc_audio_clock_info *data, case 44100: case 88200: case 176400: - if (data->soc < TEGRA_ASOC_UTILS_SOC_TEGRA186) - new_baseclock = 338688000; - else { - new_baseclock = data->clk_rates[PLLA_x11025_RATE]; - mclk = data->clk_rates[PLLA_OUT0_x11025_RATE]; - ahub_rate = data->clk_rates[AHUB_x11025_RATE]; - - if (srate <= 11025) { - /* half the pll_a_out0 to support lower - * sampling rate divider - */ - mclk = mclk >> 1; - ahub_rate = ahub_rate >> 1; - } - clk_out_rate = srate * data->mclk_scale; - } + new_pll_base = data->pll_base_rate[ODD_RATE]; + pll_out = default_pll_out_rate[ODD_RATE]; break; case 8000: case 16000: @@ -77,88 +75,67 @@ int tegra_alt_asoc_utils_set_rate(struct tegra_asoc_audio_clock_info *data, case 64000: case 96000: case 192000: - if (data->soc < TEGRA_ASOC_UTILS_SOC_TEGRA186) - new_baseclock = 368640000; - else { - new_baseclock = data->clk_rates[PLLA_x8000_RATE]; - mclk = data->clk_rates[PLLA_OUT0_x8000_RATE]; - ahub_rate = data->clk_rates[AHUB_x8000_RATE]; - - if (srate <= 8000) { - /* half the pll_a_out0 to support lower - * sampling rate divider - */ - mclk = mclk >> 1; - ahub_rate = ahub_rate >> 1; - } - clk_out_rate = srate * data->mclk_scale; - } + new_pll_base = data->pll_base_rate[EVEN_RATE]; + pll_out = default_pll_out_rate[EVEN_RATE]; break; default: return -EINVAL; } - clk_out_rate = data->mclk_rate ? data->mclk_rate : clk_out_rate; + /* reduce pll_out rate to support lower sampling rates */ + if (srate <= 11025) + pll_out = pll_out >> 1; + if (data->mclk_scale) + aud_mclk = srate * data->mclk_scale; + /* + * mclk_rate is the fixed clock from DT, this overrides mclk_scale. + * TODO: manage MCLK fixed or dynamic rate from a single DT property. + */ + aud_mclk = data->mclk_rate ? data->mclk_rate : aud_mclk; - clk_change = ((new_baseclock != data->set_baseclock) || - (mclk != data->set_mclk) || - (clk_out_rate != data->set_clk_out_rate)); - - if (!clk_change) - return 0; - - /* Don't change rate if already one dai-link is using it */ - if (data->lock_count) - return -EINVAL; - - data->set_baseclock = 0; - data->set_mclk = 0; - - err = clk_set_rate(data->clk_pll_a, new_baseclock); - if (err) { - dev_err(data->dev, "Can't set pll_a rate: %d\n", err); - return err; + if (data->set_pll_base_rate != new_pll_base) { + err = clk_set_rate(data->clk_pll_base, new_pll_base); + if (err) { + dev_err(data->dev, "Can't set clk_pll_base rate: %d\n", + err); + return err; + } + data->set_pll_base_rate = new_pll_base; } - err = clk_set_rate(data->clk_pll_a_out0, mclk); - if (err) { - dev_err(data->dev, "Can't set clk_pll_a_out0 rate: %d\n", err); - return err; + if (data->set_pll_out_rate != pll_out) { + err = clk_set_rate(data->clk_pll_out, pll_out); + if (err) { + dev_err(data->dev, "Can't set clk_pll_out rate: %d\n", + err); + return err; + } + + /* TODO: remove below once ahub rate is fixed from DT */ + err = clk_set_rate(data->clk_ahub, pll_out); + if (err) { + dev_err(data->dev, "Can't set ahub rate: %d\n", + err); + return err; + } + + data->set_pll_out_rate = pll_out; } - if (data->soc > TEGRA_ASOC_UTILS_SOC_TEGRA210) { - err = clk_set_rate(data->clk_ahub, ahub_rate); + if (data->set_aud_mclk_rate != aud_mclk) { + err = clk_set_rate(data->clk_aud_mclk, aud_mclk); if (err) { dev_err(data->dev, "Can't set clk_cdev1 rate: %d\n", err); return err; } + data->set_aud_mclk_rate = aud_mclk; } - err = clk_set_rate(data->clk_cdev1, clk_out_rate); - if (err) { - dev_err(data->dev, "Can't set clk_cdev1 rate: %d\n", err); - return err; - } - - data->set_baseclock = new_baseclock; - data->set_mclk = mclk; - data->set_clk_out_rate = clk_out_rate; - return 0; } EXPORT_SYMBOL_GPL(tegra_alt_asoc_utils_set_rate); -void tegra_alt_asoc_utils_lock_clk_rate(struct tegra_asoc_audio_clock_info *data, - int lock) -{ - if (lock) - data->lock_count++; - else if (data->lock_count) - data->lock_count--; -} -EXPORT_SYMBOL_GPL(tegra_alt_asoc_utils_lock_clk_rate); - int tegra_alt_asoc_utils_clk_enable(struct tegra_asoc_audio_clock_info *data) { int err; @@ -166,7 +143,7 @@ int tegra_alt_asoc_utils_clk_enable(struct tegra_asoc_audio_clock_info *data) if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA186) reset_control_reset(data->clk_cdev1_rst); - err = clk_prepare_enable(data->clk_cdev1); + err = clk_prepare_enable(data->clk_aud_mclk); if (err) { dev_err(data->dev, "Can't enable cdev1: %d\n", err); return err; @@ -178,7 +155,7 @@ EXPORT_SYMBOL_GPL(tegra_alt_asoc_utils_clk_enable); int tegra_alt_asoc_utils_clk_disable(struct tegra_asoc_audio_clock_info *data) { - clk_disable_unprepare(data->clk_cdev1); + clk_disable_unprepare(data->clk_aud_mclk); return 0; } @@ -187,8 +164,6 @@ EXPORT_SYMBOL_GPL(tegra_alt_asoc_utils_clk_disable); int tegra_alt_asoc_utils_init(struct tegra_asoc_audio_clock_info *data, struct device *dev, struct snd_soc_card *card) { - int ret; - data->dev = dev; data->card = card; @@ -203,38 +178,28 @@ int tegra_alt_asoc_utils_init(struct tegra_asoc_audio_clock_info *data, /* DT boot, but unknown SoC */ return -EINVAL; - data->clk_pll_a = devm_clk_get(dev, "pll_a"); - if (IS_ERR(data->clk_pll_a)) { + data->clk_pll_base = devm_clk_get(dev, "pll_a"); + if (IS_ERR(data->clk_pll_base)) { dev_err(data->dev, "Can't retrieve clk pll_a\n"); - return PTR_ERR(data->clk_pll_a); + return PTR_ERR(data->clk_pll_base); } - data->clk_pll_a_out0 = devm_clk_get(dev, "pll_a_out0"); - if (IS_ERR(data->clk_pll_a_out0)) { + data->clk_pll_out = devm_clk_get(dev, "pll_a_out0"); + if (IS_ERR(data->clk_pll_out)) { dev_err(data->dev, "Can't retrieve clk pll_a_out0\n"); - return PTR_ERR(data->clk_pll_a_out0); + return PTR_ERR(data->clk_pll_out); } - data->clk_cdev1 = devm_clk_get(dev, "extern1"); - if (IS_ERR(data->clk_cdev1)) { + data->clk_aud_mclk = devm_clk_get(dev, "extern1"); + if (IS_ERR(data->clk_aud_mclk)) { dev_err(data->dev, "Can't retrieve clk cdev1\n"); - return PTR_ERR(data->clk_cdev1); + return PTR_ERR(data->clk_aud_mclk); } - /* Control the aud mclk rate and parent for usecases which might - * need fixed rate and needs to be derived from other possible - * parents of aud mclk clk source - */ - data->clk_mclk_parent = devm_clk_get(dev, "mclk_parent"); - if (IS_ERR(data->clk_mclk_parent)) - data->clk_mclk_parent = data->clk_pll_a_out0; - - if (data->soc > TEGRA_ASOC_UTILS_SOC_TEGRA210) { - data->clk_ahub = devm_clk_get(dev, "ahub"); - if (IS_ERR(data->clk_ahub)) { - dev_err(data->dev, "Can't retrieve clk ahub\n"); - return PTR_ERR(data->clk_ahub); - } + data->clk_ahub = devm_clk_get(dev, "ahub"); + if (IS_ERR(data->clk_ahub)) { + dev_err(data->dev, "Can't retrieve clk ahub\n"); + return PTR_ERR(data->clk_ahub); } if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA186) { @@ -248,11 +213,10 @@ int tegra_alt_asoc_utils_init(struct tegra_asoc_audio_clock_info *data, reset_control_reset(data->clk_cdev1_rst); } - ret = clk_set_parent(data->clk_cdev1, data->clk_mclk_parent); - if (ret < 0) { - dev_err(card->dev, "Failed to set extern clk parent\n"); - return ret; - } + if (data->soc < TEGRA_ASOC_UTILS_SOC_TEGRA186) + data->pll_base_rate = tegra210_pll_base_rate; + else + data->pll_base_rate = tegra186_pll_base_rate; return 0; }