ASoC: tegra: Squash utils into common machine driver

There no users left of the utils other than the new common machine driver.
Squash the utils into the common machine driver in order to simplify code.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
Link: https://lore.kernel.org/r/20210529154649.25936-5-digetx@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Dmitry Osipenko 2021-05-29 18:46:49 +03:00 committed by Mark Brown
parent c16aab8ddc
commit 8c1b3b1593
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
5 changed files with 150 additions and 276 deletions

View File

@ -15,7 +15,6 @@ snd-soc-tegra186-dspk-objs := tegra186_dspk.o
snd-soc-tegra210-admaif-objs := tegra210_admaif.o
obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-pcm.o
obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-utils.o
obj-$(CONFIG_SND_SOC_TEGRA20_AC97) += snd-soc-tegra20-ac97.o
obj-$(CONFIG_SND_SOC_TEGRA20_DAS) += snd-soc-tegra20-das.o
obj-$(CONFIG_SND_SOC_TEGRA20_I2S) += snd-soc-tegra20-i2s.o

View File

@ -3,6 +3,7 @@
* tegra_asoc_machine.c - Universal ASoC machine driver for NVIDIA Tegra boards.
*/
#include <linux/clk.h>
#include <linux/export.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
@ -239,12 +240,68 @@ static int tegra_machine_hw_params(struct snd_pcm_substream *substream,
unsigned int srate = params_rate(params);
unsigned int mclk = machine->asoc->mclk_rate(srate);
unsigned int clk_id = machine->asoc->mclk_id;
unsigned int new_baseclock;
int err;
err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
if (err < 0) {
dev_err(card->dev, "Can't configure clocks: %d\n", err);
return err;
switch (srate) {
case 11025:
case 22050:
case 44100:
case 88200:
if (of_machine_is_compatible("nvidia,tegra20"))
new_baseclock = 56448000;
else if (of_machine_is_compatible("nvidia,tegra30"))
new_baseclock = 564480000;
else
new_baseclock = 282240000;
break;
case 8000:
case 16000:
case 32000:
case 48000:
case 64000:
case 96000:
if (of_machine_is_compatible("nvidia,tegra20"))
new_baseclock = 73728000;
else if (of_machine_is_compatible("nvidia,tegra30"))
new_baseclock = 552960000;
else
new_baseclock = 368640000;
break;
default:
dev_err(card->dev, "Invalid sound rate: %u\n", srate);
return -EINVAL;
}
if (new_baseclock != machine->set_baseclock ||
mclk != machine->set_mclk) {
machine->set_baseclock = 0;
machine->set_mclk = 0;
clk_disable_unprepare(machine->clk_cdev1);
err = clk_set_rate(machine->clk_pll_a, new_baseclock);
if (err) {
dev_err(card->dev, "Can't set pll_a rate: %d\n", err);
return err;
}
err = clk_set_rate(machine->clk_pll_a_out0, mclk);
if (err) {
dev_err(card->dev, "Can't set pll_a_out0 rate: %d\n", err);
return err;
}
/* Don't set cdev1/extern1 rate; it's locked to pll_a_out0 */
err = clk_prepare_enable(machine->clk_cdev1);
if (err) {
dev_err(card->dev, "Can't enable cdev1: %d\n", err);
return err;
}
machine->set_baseclock = new_baseclock;
machine->set_mclk = mclk;
}
err = snd_soc_dai_set_sysclk(codec_dai, clk_id, mclk, SND_SOC_CLOCK_IN);
@ -377,14 +434,92 @@ int tegra_asoc_machine_probe(struct platform_device *pdev)
if (!card->driver_name)
card->driver_name = "tegra";
err = tegra_asoc_utils_init(&machine->util_data, &pdev->dev);
if (err)
return err;
machine->clk_pll_a = devm_clk_get(dev, "pll_a");
if (IS_ERR(machine->clk_pll_a)) {
dev_err(dev, "Can't retrieve clk pll_a\n");
return PTR_ERR(machine->clk_pll_a);
}
machine->clk_pll_a_out0 = devm_clk_get(dev, "pll_a_out0");
if (IS_ERR(machine->clk_pll_a_out0)) {
dev_err(dev, "Can't retrieve clk pll_a_out0\n");
return PTR_ERR(machine->clk_pll_a_out0);
}
machine->clk_cdev1 = devm_clk_get(dev, "mclk");
if (IS_ERR(machine->clk_cdev1)) {
dev_err(dev, "Can't retrieve clk cdev1\n");
return PTR_ERR(machine->clk_cdev1);
}
/*
* If clock parents are not set in DT, configure here to use clk_out_1
* as mclk and extern1 as parent for Tegra30 and higher.
*/
if (!of_find_property(dev->of_node, "assigned-clock-parents", NULL) &&
!of_machine_is_compatible("nvidia,tegra20")) {
struct clk *clk_out_1, *clk_extern1;
dev_warn(dev, "Configuring clocks for a legacy device-tree\n");
dev_warn(dev, "Please update DT to use assigned-clock-parents\n");
clk_extern1 = devm_clk_get(dev, "extern1");
if (IS_ERR(clk_extern1)) {
dev_err(dev, "Can't retrieve clk extern1\n");
return PTR_ERR(clk_extern1);
}
err = clk_set_parent(clk_extern1, machine->clk_pll_a_out0);
if (err < 0) {
dev_err(dev, "Set parent failed for clk extern1\n");
return err;
}
clk_out_1 = devm_clk_get(dev, "pmc_clk_out_1");
if (IS_ERR(clk_out_1)) {
dev_err(dev, "Can't retrieve pmc_clk_out_1\n");
return PTR_ERR(clk_out_1);
}
err = clk_set_parent(clk_out_1, clk_extern1);
if (err < 0) {
dev_err(dev, "Set parent failed for pmc_clk_out_1\n");
return err;
}
machine->clk_cdev1 = clk_out_1;
}
if (asoc->set_ac97) {
err = tegra_asoc_utils_set_ac97_rate(&machine->util_data);
if (err)
/*
* AC97 rate is fixed at 24.576MHz and is used for both the
* host controller and the external codec
*/
err = clk_set_rate(machine->clk_pll_a, 73728000);
if (err) {
dev_err(dev, "Can't set pll_a rate: %d\n", err);
return err;
}
err = clk_set_rate(machine->clk_pll_a_out0, 24576000);
if (err) {
dev_err(dev, "Can't set pll_a_out0 rate: %d\n", err);
return err;
}
machine->set_baseclock = 73728000;
machine->set_mclk = 24576000;
}
/*
* FIXME: There is some unknown dependency between audio MCLK disable
* and suspend-resume functionality on Tegra30, although audio MCLK is
* only needed for audio.
*/
err = clk_prepare_enable(machine->clk_cdev1);
if (err) {
dev_err(dev, "Can't enable cdev1: %d\n", err);
return err;
}
err = devm_snd_soc_register_card(dev, card);

View File

@ -3,8 +3,7 @@
#ifndef __TEGRA_ASOC_MACHINE_H__
#define __TEGRA_ASOC_MACHINE_H__
#include "tegra_asoc_utils.h"
struct clk;
struct gpio_desc;
struct snd_soc_card;
struct snd_soc_jack;
@ -27,7 +26,11 @@ struct tegra_asoc_data {
};
struct tegra_machine {
struct tegra_asoc_utils_data util_data;
struct clk *clk_pll_a_out0;
struct clk *clk_pll_a;
struct clk *clk_cdev1;
unsigned int set_baseclock;
unsigned int set_mclk;
const struct tegra_asoc_data *asoc;
struct gpio_desc *gpiod_ext_mic_en;
struct gpio_desc *gpiod_int_mic_en;

View File

@ -1,225 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* tegra_asoc_utils.c - Harmony machine ASoC driver
*
* Author: Stephen Warren <swarren@nvidia.com>
* Copyright (C) 2010,2012 - NVIDIA, Inc.
*/
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include "tegra_asoc_utils.h"
int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
int mclk)
{
int new_baseclock;
bool clk_change;
int err;
switch (srate) {
case 11025:
case 22050:
case 44100:
case 88200:
if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA20)
new_baseclock = 56448000;
else if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA30)
new_baseclock = 564480000;
else
new_baseclock = 282240000;
break;
case 8000:
case 16000:
case 32000:
case 48000:
case 64000:
case 96000:
if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA20)
new_baseclock = 73728000;
else if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA30)
new_baseclock = 552960000;
else
new_baseclock = 368640000;
break;
default:
return -EINVAL;
}
clk_change = ((new_baseclock != data->set_baseclock) ||
(mclk != data->set_mclk));
if (!clk_change)
return 0;
data->set_baseclock = 0;
data->set_mclk = 0;
clk_disable_unprepare(data->clk_cdev1);
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;
}
err = clk_set_rate(data->clk_pll_a_out0, mclk);
if (err) {
dev_err(data->dev, "Can't set pll_a_out0 rate: %d\n", err);
return err;
}
/* Don't set cdev1/extern1 rate; it's locked to pll_a_out0 */
err = clk_prepare_enable(data->clk_cdev1);
if (err) {
dev_err(data->dev, "Can't enable cdev1: %d\n", err);
return err;
}
data->set_baseclock = new_baseclock;
data->set_mclk = mclk;
return 0;
}
EXPORT_SYMBOL_GPL(tegra_asoc_utils_set_rate);
int tegra_asoc_utils_set_ac97_rate(struct tegra_asoc_utils_data *data)
{
const int pll_rate = 73728000;
const int ac97_rate = 24576000;
int err;
clk_disable_unprepare(data->clk_cdev1);
/*
* 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);
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);
if (err) {
dev_err(data->dev, "Can't set pll_a_out0 rate: %d\n", err);
return err;
}
/* Don't set cdev1/extern1 rate; it's locked to pll_a_out0 */
err = clk_prepare_enable(data->clk_cdev1);
if (err) {
dev_err(data->dev, "Can't enable cdev1: %d\n", err);
return err;
}
data->set_baseclock = pll_rate;
data->set_mclk = ac97_rate;
return 0;
}
EXPORT_SYMBOL_GPL(tegra_asoc_utils_set_ac97_rate);
int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,
struct device *dev)
{
struct clk *clk_out_1, *clk_extern1;
int ret;
data->dev = dev;
if (of_machine_is_compatible("nvidia,tegra20"))
data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA20;
else if (of_machine_is_compatible("nvidia,tegra30"))
data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA30;
else if (of_machine_is_compatible("nvidia,tegra114"))
data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA114;
else if (of_machine_is_compatible("nvidia,tegra124"))
data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA124;
else {
dev_err(data->dev, "SoC unknown to Tegra ASoC utils\n");
return -EINVAL;
}
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");
return PTR_ERR(data->clk_pll_a);
}
data->clk_pll_a_out0 = devm_clk_get(dev, "pll_a_out0");
if (IS_ERR(data->clk_pll_a_out0)) {
dev_err(data->dev, "Can't retrieve clk pll_a_out0\n");
return PTR_ERR(data->clk_pll_a_out0);
}
data->clk_cdev1 = devm_clk_get(dev, "mclk");
if (IS_ERR(data->clk_cdev1)) {
dev_err(data->dev, "Can't retrieve clk cdev1\n");
return PTR_ERR(data->clk_cdev1);
}
/*
* If clock parents are not set in DT, configure here to use clk_out_1
* as mclk and extern1 as parent for Tegra30 and higher.
*/
if (!of_find_property(dev->of_node, "assigned-clock-parents", NULL) &&
data->soc > TEGRA_ASOC_UTILS_SOC_TEGRA20) {
dev_warn(data->dev,
"Configuring clocks for a legacy device-tree\n");
dev_warn(data->dev,
"Please update DT to use assigned-clock-parents\n");
clk_extern1 = devm_clk_get(dev, "extern1");
if (IS_ERR(clk_extern1)) {
dev_err(data->dev, "Can't retrieve clk extern1\n");
return PTR_ERR(clk_extern1);
}
ret = clk_set_parent(clk_extern1, data->clk_pll_a_out0);
if (ret < 0) {
dev_err(data->dev,
"Set parent failed for clk extern1\n");
return ret;
}
clk_out_1 = devm_clk_get(dev, "pmc_clk_out_1");
if (IS_ERR(clk_out_1)) {
dev_err(data->dev, "Can't retrieve pmc_clk_out_1\n");
return PTR_ERR(clk_out_1);
}
ret = clk_set_parent(clk_out_1, clk_extern1);
if (ret < 0) {
dev_err(data->dev,
"Set parent failed for pmc_clk_out_1\n");
return ret;
}
data->clk_cdev1 = clk_out_1;
}
/*
* FIXME: There is some unknown dependency between audio mclk disable
* and suspend-resume functionality on Tegra30, although audio mclk is
* only needed for audio.
*/
ret = clk_prepare_enable(data->clk_cdev1);
if (ret) {
dev_err(data->dev, "Can't enable cdev1: %d\n", ret);
return ret;
}
return 0;
}
EXPORT_SYMBOL_GPL(tegra_asoc_utils_init);
MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
MODULE_DESCRIPTION("Tegra ASoC utility code");
MODULE_LICENSE("GPL");

View File

@ -1,38 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* tegra_asoc_utils.h - Definitions for Tegra DAS driver
*
* Author: Stephen Warren <swarren@nvidia.com>
* Copyright (C) 2010,2012 - NVIDIA, Inc.
*/
#ifndef __TEGRA_ASOC_UTILS_H__
#define __TEGRA_ASOC_UTILS_H__
struct clk;
struct device;
enum tegra_asoc_utils_soc {
TEGRA_ASOC_UTILS_SOC_TEGRA20,
TEGRA_ASOC_UTILS_SOC_TEGRA30,
TEGRA_ASOC_UTILS_SOC_TEGRA114,
TEGRA_ASOC_UTILS_SOC_TEGRA124,
};
struct tegra_asoc_utils_data {
struct device *dev;
enum tegra_asoc_utils_soc soc;
struct clk *clk_pll_a;
struct clk *clk_pll_a_out0;
struct clk *clk_cdev1;
int set_baseclock;
int set_mclk;
};
int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
int mclk);
int tegra_asoc_utils_set_ac97_rate(struct tegra_asoc_utils_data *data);
int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,
struct device *dev);
#endif