mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 09:11:26 +03:00
ASoC: tegra-alt: fix dynamic pinmux config
Currently dynamic pinmux configuration for I2S, DMIC, DSPK modules are present in runtime_resume() function which can be called even without any audio usecase active on these modules. So this destroy the purpose of programming pinmux only during stream active state. This change has moved the dynamic pinmux code in these drivers to dai ops callback of startup and shutdown which will ensure the pinmux config happens only during the stream playback/capture. Bug 200497486 Change-Id: I3c4e8a96d0d066b38c9aba5ffe530db5cf5246fc Signed-off-by: Mohan Kumar <mkumard@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/2029745 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com> GVS: Gerrit_Virtual_Submit Reviewed-by: Dara Ramesh <dramesh@nvidia.com> Reviewed-by: Ravindra Lokhande <rlokhande@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
9050c3e455
commit
4a6ee45df7
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* tegra210_i2s_alt.h - Definitions for Tegra210 I2S driver
|
||||
*
|
||||
* Copyright (c) 2014-2018 NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (c) 2014-2019 NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -232,7 +232,7 @@ struct tegra210_i2s {
|
||||
unsigned int fsync_width;
|
||||
unsigned int tx_mask;
|
||||
unsigned int rx_mask;
|
||||
unsigned int loopback;
|
||||
bool loopback;
|
||||
unsigned int format;
|
||||
bool enable_cya;
|
||||
unsigned int rx_fifo_th; /* should be programmed interms of frames */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* tegra186_dspk_alt.c - Tegra186 DSPK driver
|
||||
*
|
||||
* Copyright (c) 2015-2018 NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (c) 2015-2019 NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -94,21 +94,12 @@ static int tegra186_dspk_put_control(struct snd_kcontrol *kcontrol,
|
||||
static int tegra186_dspk_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct tegra186_dspk *dspk = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
regcache_cache_only(dspk->regmap, true);
|
||||
regcache_mark_dirty(dspk->regmap);
|
||||
|
||||
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
|
||||
if (!IS_ERR(dspk->pin_idle_state) && dspk->is_pinctrl) {
|
||||
ret = pinctrl_select_state(
|
||||
dspk->pinctrl, dspk->pin_idle_state);
|
||||
if (ret < 0)
|
||||
dev_err(dev,
|
||||
"setting dap pinctrl idle state failed\n");
|
||||
}
|
||||
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga()))
|
||||
clk_disable_unprepare(dspk->clk_dspk);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -118,22 +109,7 @@ static int tegra186_dspk_runtime_resume(struct device *dev)
|
||||
struct tegra186_dspk *dspk = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
if (dspk->prod_name) {
|
||||
ret = tegra_pinctrl_config_prod(dev, dspk->prod_name);
|
||||
if (ret < 0)
|
||||
dev_warn(dev, "Failed to set %s setting\n",
|
||||
dspk->prod_name);
|
||||
}
|
||||
|
||||
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
|
||||
if (!IS_ERR(dspk->pin_active_state) && dspk->is_pinctrl) {
|
||||
ret = pinctrl_select_state(dspk->pinctrl,
|
||||
dspk->pin_active_state);
|
||||
if (ret < 0)
|
||||
dev_err(dev,
|
||||
"setting dap pinctrl active state failed\n");
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(dspk->clk_dspk);
|
||||
if (ret) {
|
||||
dev_err(dev, "clk_enable failed: %d\n", ret);
|
||||
@@ -214,6 +190,53 @@ static int tegra186_dspk_set_dai_bclk_ratio(struct snd_soc_dai *dai,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra186_dspk_startup(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct device *dev = dai->dev;
|
||||
struct tegra186_dspk *dspk = snd_soc_dai_get_drvdata(dai);
|
||||
int ret;
|
||||
|
||||
if (dspk->prod_name != NULL) {
|
||||
ret = tegra_pinctrl_config_prod(dev, dspk->prod_name);
|
||||
if (ret < 0)
|
||||
dev_warn(dev, "Failed to set %s setting\n",
|
||||
dspk->prod_name);
|
||||
}
|
||||
|
||||
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
|
||||
if (!IS_ERR(dspk->pin_active_state) && dspk->is_pinctrl) {
|
||||
ret = pinctrl_select_state(dspk->pinctrl,
|
||||
dspk->pin_active_state);
|
||||
if (ret < 0) {
|
||||
dev_err(dev,
|
||||
"setting dap pinctrl active state failed\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tegra186_dspk_shutdown(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct device *dev = dai->dev;
|
||||
struct tegra186_dspk *dspk = snd_soc_dai_get_drvdata(dai);
|
||||
int ret;
|
||||
|
||||
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
|
||||
if (!IS_ERR(dspk->pin_idle_state) && dspk->is_pinctrl) {
|
||||
ret = pinctrl_select_state(
|
||||
dspk->pinctrl, dspk->pin_idle_state);
|
||||
if (ret < 0) {
|
||||
dev_err(dev,
|
||||
"setting dap pinctrl idle state failed\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int tegra186_dspk_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
@@ -273,6 +296,8 @@ static int tegra186_dspk_codec_probe(struct snd_soc_codec *codec)
|
||||
static struct snd_soc_dai_ops tegra186_dspk_dai_ops = {
|
||||
.hw_params = tegra186_dspk_hw_params,
|
||||
.set_bclk_ratio = tegra186_dspk_set_dai_bclk_ratio,
|
||||
.startup = tegra186_dspk_startup,
|
||||
.shutdown = tegra186_dspk_shutdown,
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver tegra186_dspk_dais[] = {
|
||||
|
||||
@@ -75,22 +75,12 @@ static const struct reg_default tegra210_dmic_reg_defaults[] = {
|
||||
static int tegra210_dmic_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct tegra210_dmic *dmic = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
regcache_cache_only(dmic->regmap, true);
|
||||
regcache_mark_dirty(dmic->regmap);
|
||||
|
||||
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
|
||||
if (!IS_ERR(dmic->pin_idle_state) && dmic->is_pinctrl) {
|
||||
ret = pinctrl_select_state(
|
||||
dmic->pinctrl, dmic->pin_idle_state);
|
||||
if (ret < 0)
|
||||
dev_err(dev,
|
||||
"setting dap pinctrl idle state failed\n");
|
||||
}
|
||||
|
||||
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga()))
|
||||
clk_disable_unprepare(dmic->clk_dmic);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -100,22 +90,7 @@ static int tegra210_dmic_runtime_resume(struct device *dev)
|
||||
struct tegra210_dmic *dmic = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
if (dmic->prod_name) {
|
||||
ret = tegra_pinctrl_config_prod(dev, dmic->prod_name);
|
||||
if (ret < 0)
|
||||
dev_warn(dev, "Failed to set %s setting\n",
|
||||
dmic->prod_name);
|
||||
}
|
||||
|
||||
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
|
||||
if (!IS_ERR(dmic->pin_active_state) && dmic->is_pinctrl) {
|
||||
ret = pinctrl_select_state(dmic->pinctrl,
|
||||
dmic->pin_active_state);
|
||||
if (ret < 0)
|
||||
dev_err(dev,
|
||||
"setting dap pinctrl active state failed\n");
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(dmic->clk_dmic);
|
||||
if (ret) {
|
||||
dev_err(dev, "clk_enable failed: %d\n", ret);
|
||||
@@ -123,7 +98,6 @@ static int tegra210_dmic_runtime_resume(struct device *dev)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
regcache_cache_only(dmic->regmap, false);
|
||||
|
||||
if (!dmic->is_shutdown)
|
||||
@@ -251,6 +225,52 @@ int tegra210_dmic_set_start_callback(int id, void (*callback)(void))
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tegra210_dmic_set_start_callback);
|
||||
|
||||
static int tegra210_dmic_startup(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct device *dev = dai->dev;
|
||||
struct tegra210_dmic *dmic = snd_soc_dai_get_drvdata(dai);
|
||||
int ret;
|
||||
|
||||
if (dmic->prod_name != NULL) {
|
||||
ret = tegra_pinctrl_config_prod(dev, dmic->prod_name);
|
||||
if (ret < 0) {
|
||||
dev_warn(dev, "Failed to set %s setting\n",
|
||||
dmic->prod_name);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
|
||||
if (!IS_ERR(dmic->pin_active_state) && dmic->is_pinctrl) {
|
||||
ret = pinctrl_select_state(dmic->pinctrl,
|
||||
dmic->pin_active_state);
|
||||
if (ret < 0) {
|
||||
dev_err(dev,
|
||||
"setting dap pinctrl active state failed\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tegra210_dmic_shutdown(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct device *dev = dai->dev;
|
||||
struct tegra210_dmic *dmic = snd_soc_dai_get_drvdata(dai);
|
||||
int ret;
|
||||
|
||||
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
|
||||
if (!IS_ERR(dmic->pin_idle_state) && dmic->is_pinctrl) {
|
||||
ret = pinctrl_select_state(
|
||||
dmic->pinctrl, dmic->pin_idle_state);
|
||||
if (ret < 0)
|
||||
dev_err(dev,
|
||||
"setting dap pinctrl idle state failed\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int tegra210_dmic_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
@@ -468,6 +488,8 @@ static int tegra210_dmic_codec_probe(struct snd_soc_codec *codec)
|
||||
static struct snd_soc_dai_ops tegra210_dmic_dai_ops = {
|
||||
.hw_params = tegra210_dmic_hw_params,
|
||||
.set_bclk_ratio = tegra210_dmic_set_dai_bclk_ratio,
|
||||
.startup = tegra210_dmic_startup,
|
||||
.shutdown = tegra210_dmic_shutdown,
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver tegra210_dmic_dais[] = {
|
||||
|
||||
@@ -220,29 +220,12 @@ static int tegra210_i2s_tx_stop(struct snd_soc_dapm_widget *w,
|
||||
static int tegra210_i2s_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct tegra210_i2s *i2s = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
regcache_cache_only(i2s->regmap, true);
|
||||
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
|
||||
if (!IS_ERR(i2s->pin_idle_state)) {
|
||||
ret = pinctrl_select_state(
|
||||
i2s->pinctrl, i2s->pin_idle_state);
|
||||
if (ret < 0)
|
||||
dev_err(dev, "setting dap pinctrl idle state failed\n");
|
||||
}
|
||||
|
||||
if (i2s->num_supplies > 0) {
|
||||
ret = regulator_bulk_disable(i2s->num_supplies,
|
||||
i2s->supplies);
|
||||
if (ret < 0)
|
||||
dev_err(dev, "failed to disable i2s io regulator\n");
|
||||
}
|
||||
|
||||
regcache_cache_only(i2s->regmap, true);
|
||||
regcache_mark_dirty(i2s->regmap);
|
||||
|
||||
clk_disable_unprepare(i2s->clk_i2s);
|
||||
} else
|
||||
regcache_cache_only(i2s->regmap, true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -253,27 +236,6 @@ static int tegra210_i2s_runtime_resume(struct device *dev)
|
||||
int ret;
|
||||
|
||||
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
|
||||
if (i2s->prod_name) {
|
||||
ret = tegra_pinctrl_config_prod(dev, i2s->prod_name);
|
||||
if (ret < 0)
|
||||
dev_warn(dev, "Failed to set %s setting\n",
|
||||
i2s->prod_name);
|
||||
}
|
||||
|
||||
if (!IS_ERR(i2s->pin_default_state)) {
|
||||
ret = pinctrl_select_state(i2s->pinctrl,
|
||||
i2s->pin_default_state);
|
||||
if (ret < 0)
|
||||
dev_err(dev, "setting dap pinctrl default state failed\n");
|
||||
}
|
||||
|
||||
if (i2s->num_supplies > 0) {
|
||||
ret = regulator_bulk_enable(i2s->num_supplies,
|
||||
i2s->supplies);
|
||||
if (ret < 0)
|
||||
dev_err(dev, "failed to enable i2s io regulator\n");
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(i2s->clk_i2s);
|
||||
if (ret) {
|
||||
dev_err(dev, "clk_enable failed: %d\n", ret);
|
||||
@@ -281,7 +243,6 @@ static int tegra210_i2s_runtime_resume(struct device *dev)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
regcache_cache_only(i2s->regmap, false);
|
||||
if (!i2s->is_shutdown)
|
||||
regcache_sync(i2s->regmap);
|
||||
@@ -536,6 +497,69 @@ static const struct soc_enum tegra210_i2s_format_enum =
|
||||
ARRAY_SIZE(tegra210_i2s_format_text),
|
||||
tegra210_i2s_format_text);
|
||||
|
||||
static int tegra210_i2s_startup(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct device *dev = dai->dev;
|
||||
struct tegra210_i2s *i2s = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga()) &&
|
||||
!i2s->loopback) {
|
||||
if (i2s->prod_name != NULL) {
|
||||
ret = tegra_pinctrl_config_prod(dev, i2s->prod_name);
|
||||
if (ret < 0) {
|
||||
dev_warn(dev, "Failed to set %s setting\n",
|
||||
i2s->prod_name);
|
||||
}
|
||||
}
|
||||
|
||||
if (!IS_ERR(i2s->pin_default_state)) {
|
||||
ret = pinctrl_select_state(i2s->pinctrl,
|
||||
i2s->pin_default_state);
|
||||
if (ret < 0)
|
||||
dev_err(dev, "setting dap pinctrl default state failed\n");
|
||||
}
|
||||
|
||||
if (i2s->num_supplies > 0) {
|
||||
ret = regulator_bulk_enable(i2s->num_supplies,
|
||||
i2s->supplies);
|
||||
if (ret < 0)
|
||||
dev_err(dev, "failed to enable i2s io regulator\n");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tegra210_i2s_shutdown(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct device *dev = dai->dev;
|
||||
struct tegra210_i2s *i2s = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
|
||||
if (!IS_ERR(i2s->pin_idle_state)) {
|
||||
ret = pinctrl_select_state(
|
||||
i2s->pinctrl, i2s->pin_idle_state);
|
||||
if (ret < 0) {
|
||||
dev_err(dev,
|
||||
"setting dap pinctrl idle state failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (i2s->num_supplies > 0) {
|
||||
ret = regulator_bulk_disable(i2s->num_supplies,
|
||||
i2s->supplies);
|
||||
if (ret < 0) {
|
||||
dev_err(dev,
|
||||
"failed to disable i2s io regulator\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int tegra210_i2s_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
@@ -717,6 +741,8 @@ static struct snd_soc_dai_ops tegra210_i2s_dai_ops = {
|
||||
.hw_params = tegra210_i2s_hw_params,
|
||||
.set_bclk_ratio = tegra210_i2s_set_dai_bclk_ratio,
|
||||
.set_tdm_slot = tegra210_i2s_set_tdm_slot,
|
||||
.startup = tegra210_i2s_startup,
|
||||
.shutdown = tegra210_i2s_shutdown,
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver tegra210_i2s_dais[] = {
|
||||
|
||||
Reference in New Issue
Block a user