mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 17:25:35 +03:00
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 <mkumard@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/2111340 Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com> Reviewed-by: Jonathan Hunter <jonathanh@nvidia.com> GVS: Gerrit_Virtual_Submit Reviewed-by: Sameer Pujar <spujar@nvidia.com> Reviewed-by: Sharad Gupta <sharadg@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
committed by
Sameer Pujar
parent
7c8718b81e
commit
52f2d67cf4
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,22 +260,20 @@ 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");
|
||||
dev_err(data->dev, "Can't set aud mclk clock parent");
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
err = clk_set_rate(data->clk_cdev1, rate);
|
||||
if (err) {
|
||||
|
||||
Reference in New Issue
Block a user