diff --git a/sound/soc/tegra/tegra_asoc_utils.c b/sound/soc/tegra/tegra_asoc_utils.c index 587f62a2..d1551316 100644 --- a/sound/soc/tegra/tegra_asoc_utils.c +++ b/sound/soc/tegra/tegra_asoc_utils.c @@ -15,6 +15,20 @@ #include "tegra_asoc_utils.h" +/* + * this will be used for platforms from Tegra210 onwards. + * odd rates: sample rates multiple of 11.025kHz + * even_rates: sample rates multiple of 8kHz + */ +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_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate, int mclk) { @@ -59,25 +73,47 @@ int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate, data->set_baseclock = 0; data->set_mclk = 0; +<<<<<<< HEAD + clk_disable_unprepare(data->clk_aud_mclk); + clk_disable_unprepare(data->clk_pll_out); + clk_disable_unprepare(data->clk_pll); +======= clk_disable_unprepare(data->clk_cdev1); +>>>>>>> v5.8-rc3 - err = clk_set_rate(data->clk_pll_a, new_baseclock); + err = clk_set_rate(data->clk_pll, new_baseclock); if (err) { - dev_err(data->dev, "Can't set pll_a rate: %d\n", err); + dev_err(data->dev, "Can't set base pll rate: %d\n", err); return err; } - err = clk_set_rate(data->clk_pll_a_out0, mclk); + err = clk_set_rate(data->clk_pll_out, mclk); if (err) { - dev_err(data->dev, "Can't set pll_a_out0 rate: %d\n", err); + dev_err(data->dev, "Can't set pll_out rate: %d\n", err); return err; } - /* Don't set cdev1/extern1 rate; it's locked to pll_a_out0 */ + /* Don't set cdev1/extern1 rate; it's locked to pll_out */ +<<<<<<< HEAD + err = clk_prepare_enable(data->clk_pll); + if (err) { + dev_err(data->dev, "Can't enable pll: %d\n", err); + return err; + } + + err = clk_prepare_enable(data->clk_pll_out); + if (err) { + dev_err(data->dev, "Can't enable pll_out: %d\n", err); + return err; + } + + err = clk_prepare_enable(data->clk_aud_mclk); +======= err = clk_prepare_enable(data->clk_cdev1); +>>>>>>> v5.8-rc3 if (err) { - dev_err(data->dev, "Can't enable cdev1: %d\n", err); + dev_err(data->dev, "Can't enable aud_mclk: %d\n", err); return err; } @@ -94,19 +130,25 @@ int tegra_asoc_utils_set_ac97_rate(struct tegra_asoc_utils_data *data) const int ac97_rate = 24576000; int err; +<<<<<<< HEAD + clk_disable_unprepare(data->clk_aud_mclk); + clk_disable_unprepare(data->clk_pll_out); + clk_disable_unprepare(data->clk_pll); +======= clk_disable_unprepare(data->clk_cdev1); +>>>>>>> v5.8-rc3 /* * AC97 rate is fixed at 24.576MHz and is used for both the host * controller and the external codec */ - err = clk_set_rate(data->clk_pll_a, pll_rate); + err = clk_set_rate(data->clk_pll, pll_rate); if (err) { dev_err(data->dev, "Can't set pll_a rate: %d\n", err); return err; } - err = clk_set_rate(data->clk_pll_a_out0, ac97_rate); + err = clk_set_rate(data->clk_pll_out, ac97_rate); if (err) { dev_err(data->dev, "Can't set pll_a_out0 rate: %d\n", err); return err; @@ -114,7 +156,23 @@ int tegra_asoc_utils_set_ac97_rate(struct tegra_asoc_utils_data *data) /* Don't set cdev1/extern1 rate; it's locked to pll_a_out0 */ +<<<<<<< HEAD + err = clk_prepare_enable(data->clk_pll); + if (err) { + dev_err(data->dev, "Can't enable pll_a: %d\n", err); + return err; + } + + err = clk_prepare_enable(data->clk_pll_out); + if (err) { + dev_err(data->dev, "Can't enable pll_a_out0: %d\n", err); + return err; + } + + err = clk_prepare_enable(data->clk_aud_mclk); +======= err = clk_prepare_enable(data->clk_cdev1); +>>>>>>> v5.8-rc3 if (err) { dev_err(data->dev, "Can't enable cdev1: %d\n", err); return err; @@ -127,6 +185,94 @@ int tegra_asoc_utils_set_ac97_rate(struct tegra_asoc_utils_data *data) } EXPORT_SYMBOL_GPL(tegra_asoc_utils_set_ac97_rate); +int tegra_asoc_utils_set_tegra210_rate(struct tegra_asoc_utils_data *data, + unsigned int sample_rate) +{ + unsigned int new_pll_base, pll_out, aud_mclk = 0; + int err; + + switch (sample_rate) { + case 11025: + case 22050: + case 44100: + case 88200: + case 176400: + new_pll_base = data->pll_base_rate[ODD_RATE]; + pll_out = default_pll_out_rate[ODD_RATE]; + break; + case 8000: + case 16000: + case 32000: + case 48000: + case 96000: + case 192000: + new_pll_base = data->pll_base_rate[EVEN_RATE]; + pll_out = default_pll_out_rate[EVEN_RATE]; + break; + default: + return -EINVAL; + } + + /* reduce pll_out rate to support lower sampling rates */ + if (sample_rate <= 11025) + pll_out = pll_out >> 1; + if (data->mclk_fs) + aud_mclk = sample_rate * data->mclk_fs; + + if (data->set_baseclock != new_pll_base) { + err = clk_set_rate(data->clk_pll, new_pll_base); + if (err) { + dev_err(data->dev, "Can't set clk_pll rate: %d\n", + err); + return err; + } + data->set_baseclock = new_pll_base; + } + + if (data->set_pll_out != 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; + } + data->set_pll_out = pll_out; + } + + if (data->set_mclk != 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_mclk = aud_mclk; + } + + return 0; +} +EXPORT_SYMBOL_GPL(tegra_asoc_utils_set_tegra210_rate); + +int tegra_asoc_utils_clk_enable(struct tegra_asoc_utils_data *data) +{ + int err; + + err = clk_prepare_enable(data->clk_aud_mclk); + if (err) { + dev_err(data->dev, "Can't enable clock aud_mclk\n"); + return err; + } + + return 0; +} +EXPORT_SYMBOL_GPL(tegra_asoc_utils_clk_enable); + +void tegra_asoc_utils_clk_disable(struct tegra_asoc_utils_data *data) +{ + clk_disable_unprepare(data->clk_aud_mclk); +} +EXPORT_SYMBOL_GPL(tegra_asoc_utils_clk_disable); + int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data, struct device *dev) { @@ -143,11 +289,47 @@ int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data, data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA114; else if (of_machine_is_compatible("nvidia,tegra124")) data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA124; + else if (of_machine_is_compatible("nvidia,tegra210")) + data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA210; + else if (of_machine_is_compatible("nvidia,tegra186")) + data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA186; + else if (of_machine_is_compatible("nvidia,tegra194")) + data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA194; else { dev_err(data->dev, "SoC unknown to Tegra ASoC utils\n"); return -EINVAL; } +<<<<<<< HEAD + data->clk_pll = devm_clk_get(dev, "pll_a"); + if (IS_ERR(data->clk_pll)) { + dev_err(data->dev, "Can't retrieve clk pll_a\n"); + return PTR_ERR(data->clk_pll); + } + + 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_out); + } + + data->clk_aud_mclk = devm_clk_get(dev, "extern1"); + if (IS_ERR(data->clk_aud_mclk)) { + dev_err(data->dev, "Can't retrieve clk aud_mclk\n"); + return PTR_ERR(data->clk_aud_mclk); + } + + if (data->soc < TEGRA_ASOC_UTILS_SOC_TEGRA210) { + ret = tegra_asoc_utils_set_rate(data, 44100, 256 * 44100); + if (ret) + 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; +======= data->clk_pll_a = devm_clk_get(dev, "pll_a"); if (IS_ERR(data->clk_pll_a)) { dev_err(data->dev, "Can't retrieve clk pll_a\n"); @@ -215,6 +397,7 @@ int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data, dev_err(data->dev, "Can't enable cdev1: %d\n", ret); return ret; } +>>>>>>> v5.8-rc3 return 0; }