From 52f2d67cf44eb0e87b0529eb3280866890227881 Mon Sep 17 00:00:00 2001 From: Mohan Kumar Date: Fri, 3 May 2019 14:03:23 +0530 Subject: [PATCH] ASoC: tegra-alt: aud mclk clock control via DT Added support to control the aud mclk parent, rate and scaling factor from the dt entry which can be optional. With this support, the aud mclk can be set to all possible aud mclk clock parent, also can set the desired fixed rate and scale the aud_mclk as a function of Fs. Bug 200513507 Change-Id: I80d776b7d157c49040d2da8b95b046c21926003b Signed-off-by: Mohan Kumar Reviewed-on: https://git-master.nvidia.com/r/2111340 Reviewed-by: svc-mobile-coverity Reviewed-by: Jonathan Hunter GVS: Gerrit_Virtual_Submit Reviewed-by: Sameer Pujar Reviewed-by: Sharad Gupta Reviewed-by: mobile promotions Tested-by: mobile promotions --- .../tegra-alt/include/tegra_asoc_utils_alt.h | 9 +++-- .../tegra_machine_driver_mobile.c | 15 +++++++- .../tegra-alt/utils/tegra_asoc_utils_alt.c | 37 ++++++++++--------- 3 files changed, 38 insertions(+), 23 deletions(-) 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 dbb0e3db..4428a220 100644 --- a/sound/soc/tegra-alt/include/tegra_asoc_utils_alt.h +++ b/sound/soc/tegra-alt/include/tegra_asoc_utils_alt.h @@ -59,17 +59,18 @@ struct tegra_asoc_audio_clock_info { int set_mclk; int lock_count; int set_baseclock; - int set_clk_out_rate; int num_clk; - unsigned int clk_out_rate; - unsigned int mclk_scale; + struct clk *clk_mclk_parent; + u32 set_clk_out_rate; + u32 mclk_rate; + u32 mclk_scale; u32 clk_rates[MAX_NUM_RATES]; }; int tegra_alt_asoc_utils_set_rate(struct tegra_asoc_audio_clock_info *data, int srate, int mclk, - int clk_out_rate); + u32 clk_out_rate); void tegra_alt_asoc_utils_lock_clk_rate( struct tegra_asoc_audio_clock_info *data, int lock); 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 88dc5235..bf96a788 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 @@ -514,10 +514,11 @@ static int tegra_machine_dai_init(struct snd_soc_pcm_runtime *runtime, } if (machine->soc_data->is_clk_rate_via_dt) - clk_out_rate = machine->audio_clock.clk_out_rate; + clk_out_rate = machine->audio_clock.set_clk_out_rate; pr_debug("pll_a_out0 = %d Hz, aud_mclk = %d Hz, codec rate = %d Hz\n", - machine->audio_clock.set_mclk, clk_out_rate, clk_rate); + machine->audio_clock.set_mclk, + machine->audio_clock.set_clk_out_rate, clk_rate); /* TODO: should we pass here clk_rate ? */ err = tegra_machine_set_params(card, machine, rate, channels, formats); @@ -1075,6 +1076,16 @@ static int tegra_machine_driver_probe(struct platform_device *pdev) if (ret) goto err; + if (of_property_read_u32(np, "nvidia,mclk-rate", + &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 = 256; + dev_dbg(&pdev->dev, "Missing property mclk-fs\n"); + } + if (machine->soc_data->is_clk_rate_via_dt) { if (of_property_read_u32(np, "nvidia,num-clk", &machine->audio_clock.num_clk) < 0) { 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 d84cc2a8..0bbbdcaa 100644 --- a/sound/soc/tegra-alt/utils/tegra_asoc_utils_alt.c +++ b/sound/soc/tegra-alt/utils/tegra_asoc_utils_alt.c @@ -40,7 +40,7 @@ int tegra_alt_asoc_utils_set_rate(struct tegra_asoc_audio_clock_info *data, int srate, int mclk, - int clk_out_rate) + u32 clk_out_rate) { int new_baseclock; int ahub_rate = 0; @@ -67,9 +67,7 @@ int tegra_alt_asoc_utils_set_rate(struct tegra_asoc_audio_clock_info *data, mclk = mclk >> 1; ahub_rate = ahub_rate >> 1; } - clk_out_rate = srate * data->mclk_scale; - data->clk_out_rate = clk_out_rate; } break; case 8000: @@ -93,15 +91,15 @@ int tegra_alt_asoc_utils_set_rate(struct tegra_asoc_audio_clock_info *data, mclk = mclk >> 1; ahub_rate = ahub_rate >> 1; } - clk_out_rate = srate * data->mclk_scale; - data->clk_out_rate = clk_out_rate; } break; default: return -EINVAL; } + clk_out_rate = data->mclk_rate ? data->mclk_rate : clk_out_rate; + clk_change = ((new_baseclock != data->set_baseclock) || (mclk != data->set_mclk) || (clk_out_rate != data->set_clk_out_rate)); @@ -191,7 +189,6 @@ int tegra_alt_asoc_utils_init(struct tegra_asoc_audio_clock_info *data, { data->dev = dev; data->card = card; - data->mclk_scale = 256; if (of_machine_is_compatible("nvidia,tegra210") || of_machine_is_compatible("nvidia,tegra210b01")) @@ -228,6 +225,14 @@ int tegra_alt_asoc_utils_init(struct tegra_asoc_audio_clock_info *data, return PTR_ERR(data->clk_cdev1); } + /* 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)) + dev_dbg(data->dev, "Can't retrieve mclk parent clk\n"); + if (data->soc > TEGRA_ASOC_UTILS_SOC_TEGRA210) { data->clk_ahub = devm_clk_get(dev, "ahub"); if (IS_ERR(data->clk_ahub)) { @@ -255,21 +260,19 @@ int tegra_alt_asoc_utils_set_extern_parent( struct tegra_asoc_audio_clock_info *data, const char *parent) { unsigned long rate; - int err; + int err = 0; rate = clk_get_rate(data->clk_cdev1); - if (!strcmp(parent, "clk_m")) { + if (!IS_ERR(data->clk_mclk_parent)) + err = clk_set_parent(data->clk_cdev1, data->clk_mclk_parent); + else if (!strcmp(parent, "clk_m")) err = clk_set_parent(data->clk_cdev1, data->clk_m); - if (err) { - dev_err(data->dev, "Can't set clk extern1 parent"); - return err; - } - } else if (!strcmp(parent, "pll_a_out0")) { + else if (!strcmp(parent, "pll_a_out0")) err = clk_set_parent(data->clk_cdev1, data->clk_pll_a_out0); - if (err) { - dev_err(data->dev, "Can't set clk cdev1/extern1 parent"); - return err; - } + + if (err) { + dev_err(data->dev, "Can't set aud mclk clock parent"); + return err; } err = clk_set_rate(data->clk_cdev1, rate);